Java static final 字段初始化顺序
Java static final field initialization order
我试图理解当静态字段通过引用相同的封闭 class 对象来初始化时初始化顺序的行为。
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
[= 的声明之前22=]
static final a=5
它是 final
所以它首先初始化,在其他静态成员或方法之前。
在第一种情况下 main()
方法首先被执行,并将 a
初始化为其默认值 0
。
静态最终成员在其他静态成员之前初始化。
非final静态成员按出现顺序初始化
因此,在您的第一种情况下:
static Test t=new Test();
static int a=5;
在初始化a
之前首先调用构造函数,所以显示a=0
。
第二种情况,static final a
先于t
初始化,所以Test
的第一个实例创建时显示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.
你看到最终 class 变量(即静态最终)只有在它们的值是编译时 constant expressions 时才会在其余静态变量之前初始化。 5
是常量表达式。 new Test()
不是。因此 a
在 t
之前初始化,即使两者都是静态最终的。
静态变量在 class 被 class 加载程序加载时初始化。所以当第一行“static Test t=new Test();”被执行时,int “a” 的值尚未初始化,因此它显示为 0。但是其他 3 种情况(即删除 static,添加 final 或没有任何修饰符)发生的事情 a 在对象创建时被初始化测试 class,这发生在第一行,因此它显示值“5”。
Java Language specification 是了解初始化顺序的最佳来源。根据您的场景, static final
字段在任何 class 级别变量初始化之前被初始化。当您删除 final 时,初始化被推迟。如果改了也要注意
static Test t=new Test();
static int a=5;
到
static int a=5;
static Test t=new Test();
它也会打印
a = 5
a = 5
因为初始化顺序。
我试图理解当静态字段通过引用相同的封闭 class 对象来初始化时初始化顺序的行为。
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
[= 的声明之前22=]
static final a=5
它是 final
所以它首先初始化,在其他静态成员或方法之前。
在第一种情况下 main()
方法首先被执行,并将 a
初始化为其默认值 0
。
静态最终成员在其他静态成员之前初始化。
非final静态成员按出现顺序初始化
因此,在您的第一种情况下:
static Test t=new Test();
static int a=5;
在初始化a
之前首先调用构造函数,所以显示a=0
。
第二种情况,static final a
先于t
初始化,所以Test
的第一个实例创建时显示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.
你看到最终 class 变量(即静态最终)只有在它们的值是编译时 constant expressions 时才会在其余静态变量之前初始化。 5
是常量表达式。 new Test()
不是。因此 a
在 t
之前初始化,即使两者都是静态最终的。
静态变量在 class 被 class 加载程序加载时初始化。所以当第一行“static Test t=new Test();”被执行时,int “a” 的值尚未初始化,因此它显示为 0。但是其他 3 种情况(即删除 static,添加 final 或没有任何修饰符)发生的事情 a 在对象创建时被初始化测试 class,这发生在第一行,因此它显示值“5”。
Java Language specification 是了解初始化顺序的最佳来源。根据您的场景, static final
字段在任何 class 级别变量初始化之前被初始化。当您删除 final 时,初始化被推迟。如果改了也要注意
static Test t=new Test();
static int a=5;
到
static int a=5;
static Test t=new Test();
它也会打印
a = 5
a = 5
因为初始化顺序。