java - 静态初始化程序是否必须按分层顺序执行?

标签 java static classloader operator-precedence static-initializer

假设我有课

class A{
    public final static TreeMap<String,String> tmap = new TreeMap<>();
    int x;

    static{
        tmap.put("x:I", "Hello");
    }
}

我创建了一个子类

class B extends A{
    long y;

    static{
        tmap.put("y:J","World");
    }
}

如果我现在编写一些代码来检查静态初始化器:

class Main{
    public static void main (String[] args){
        B b = new B();
        for(String v : b.tmap.values()){
            System.out.println(v);
        }
    }
}

我知道这两个条目必须位于 tmap 中,因为 A 必须最终加载,以供 B 最晚进行 super 调用.

但是如果我正在阅读When does static class initialization happen?正确地,我不能假设 Hello 值始终首先放入映射中,因为 tmap 是最终的。

因此,如果排序很重要(假设我知道某些值可能会在层次结构中进一步更新/覆盖),我是否需要删除 final 修饰符?

或者是否有其他东西已经强制执行“正确的”静态初始化程序排序?

最佳答案

静态初始化总是在子类初始化之前为父类(super class)完成,如果有多个静态初始化 block ,它们将按顺序执行。 (编辑: 感谢 Holger 指出这不必在加载类时直接进行)。

在您的示例中,B 扩展了 A,因此类加载器必须在 B 之前加载 A。因此,首先执行 A 的静态初始化程序。

这与final修饰符无关。另一个线程可能指的是,如果编译器可以执行常量折叠( https://www.javaworld.com/article/2076060/build-ci-sdlc/compiler-optimizations.html ),则从中获取常量的类将不会被静态初始化(因为引用在编译时被替换)。

关于java - 静态初始化程序是否必须按分层顺序执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48404245/

相关文章:

java - 当探查器无法收集样本时,如何调试无响应的服务器?

java - 使用 jaxb 从 xsd 中选择生成 java 类

java - ActiveMQ 中代理的动态名称,可在同一台计算机上运行 2 个或多个实例

c++ - 在类中声明和定义的静态常量变量。如何在同一项目中另一个类的私有(private)访问中访问它。是否可以?

java - 如何从Java中的其他类初始化静态最终变量

Java android java.util.ConcurrentModificationException

PHP: "Call to undefined method"... 但方法已定义?

Java 类加载器委托(delegate)

jboss - ClassNotFoundException 引用 JBoss AS 7 中的 hornetq 特定内容

java - 如何使动态加载的插件能够感知 Web 应用程序