静态初始化程序是否必须按层次顺序执行?
Are static initialisers necessarily executed in hierarchical order?
假设我有一个 class
class A{
public final static TreeMap<String,String> tmap = new TreeMap<>();
int x;
static{
tmap.put("x:I", "Hello");
}
}
我创建了一个子class
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
的超级调用加载。
但是如果我 When does static class initialization happen? 的读法正确,我 不能 假设 Hello
值始终首先放入地图,因为 tmap
是最终的。
因此,如果排序很重要(假设我知道某些值可能 updated/overwritten 在层次结构的下方),我是否需要删除 final
修饰符?
或者是否有其他东西已经强制执行 "proper" 静态初始化程序排序?
静态初始化总是在子初始化之前为超级class完成,如果您有多个静态初始化块,它们将按顺序执行。 (编辑: 感谢 Holger 指出加载 class 时不必直接这样做 )。
在您的示例中,B 扩展了 A,因此 classloader 必须在加载 B 之前加载 A。因此,首先执行 A 的静态初始化程序。
这与final修饰符无关。另一个线程可能指的是,如果编译器可以执行常量折叠(https://www.javaworld.com/article/2076060/build-ci-sdlc/compiler-optimizations.html),则从中获取常量的class将不会被静态初始化(因为引用在编译时被替换).
假设我有一个 class
class A{
public final static TreeMap<String,String> tmap = new TreeMap<>();
int x;
static{
tmap.put("x:I", "Hello");
}
}
我创建了一个子class
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
的超级调用加载。
但是如果我 When does static class initialization happen? 的读法正确,我 不能 假设 Hello
值始终首先放入地图,因为 tmap
是最终的。
因此,如果排序很重要(假设我知道某些值可能 updated/overwritten 在层次结构的下方),我是否需要删除 final
修饰符?
或者是否有其他东西已经强制执行 "proper" 静态初始化程序排序?
静态初始化总是在子初始化之前为超级class完成,如果您有多个静态初始化块,它们将按顺序执行。 (编辑: 感谢 Holger 指出加载 class 时不必直接这样做 )。
在您的示例中,B 扩展了 A,因此 classloader 必须在加载 B 之前加载 A。因此,首先执行 A 的静态初始化程序。
这与final修饰符无关。另一个线程可能指的是,如果编译器可以执行常量折叠(https://www.javaworld.com/article/2076060/build-ci-sdlc/compiler-optimizations.html),则从中获取常量的class将不会被静态初始化(因为引用在编译时被替换).