我试图理解当使用对同一封闭类对象的引用来初始化静态字段时初始化顺序的行为。
public class Test {
static final Test t=new Test();
static int a=5;
Test(){
System.out.println("a="+a);
}
public static void main(String[] args) {
new Test();
}
}
上面这段代码的输出是:
a=0
a=5
如果我将变量 a
修改为普通 static
以外的任何其他内容:
static final a=5;
a=5;
final a=5;
输出是:
a=5
a=5
为什么会这样?
请注意,即使 t 和 a
都声明为 static final
,在这种情况下,输出也是 a=5 & a=5
t
在 a
最佳答案
静态最终成员在其他静态成员之前初始化。
非final静态成员按出现顺序初始化
因此,在您的第一种情况下:
static Test t=new Test();
static int a=5;
在a
初始化之前先调用构造函数,所以显示a=0
。
在第二种情况下,static final a
在t
之前被初始化,所以a=5
在第一个实例时显示>测试
已创建。当 a
不是静态时,它会在构造函数执行之前进行初始化,因此再次显示 a=5
。
关于您问题中的修改。
查看 12.4.2 of the JLS 部分:
- Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
...
- Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
您看到最终类变量(即 static final)只有在它们的值是编译时 constant expressions 时才会在其余静态变量之前初始化。 . 5
是常量表达式。 new Test()
不是。因此 a
在 t
之前初始化,即使两者都是静态最终的。
关于Java静态final字段初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27859435/