我找不到任何具体的SO帖子提到这个具体案例,所以我想问一下我认为是/否的问题。
这是JLS §12.4.2(Java SE 8),列出6-7:
- [...]然后, 初始化C的静态字段,它们是常量变量 (§4.12.4,§8.3.2,§9.3.1)。
- 接下来,如果C是一个类而不是一个接口,并且它的超类尚未初始化,那么让SC成为它的超类[...]对于列表中的每个S [SC,SI1,..., SIn],递归执行整个过程 对于S.如有必要,请先验证并准备S. [...]
醇>
我的问题:是否意味着在超类的静态初始化之前初始化子类的最终静态变量(假设最终的静态初始化为其声明的一部分)?
答案 0 :(得分:1)
答案是可能是这样的。关键部分是constant字义。
考虑这段代码
class Foo {
public static final int FOO_VALUE = 1000;
static {
System.err.println("FOO Bar.BAR_VALUE=" + Bar.BAR_VALUE);
}
}
class Bar extends Foo {
public static final int BAR_VALUE = 2000;
static {
System.err.println("BAR Foo.FOO_VALUE=" + Foo.FOO_VALUE);
}
}
该程序的输出将是
FOO Bar.BAR_VALUE=2000
BAR Foo.FOO_VALUE=1000
在这种情况下,Bar
静态最终变量在Foo
静态初始化之前初始化。 FOO_VALUE
和BAR_VALUE
都是常量,因此javac
可以内联此字段。
但是你可以假装最终变量不是这样的常量来欺骗编译器
class Foo {
public static final int FOO_VALUE = Integer.valueOf(1000).intValue();
static {
System.err.println("FOO " + Bar.BAR_VALUE);
}
}
class Bar extends Foo {
public static final int BAR_VALUE = Integer.valueOf(2000).intValue();
static {
System.err.println("BAR " + Foo.FOO_VALUE);
}
}
输出将是
FOO Bar.BAR_VALUE=0
BAR Foo.FOO_VALUE=1000
因此Foo
静态初始值设定项在静态最终Bar.BAR_VALUE
初始化之前完成。