Java静态最终字段初始化顺序
我尝试通过引用同一个封闭类对象初始化静态字段时了解初始化顺序的行为。
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
静态最终成员在其他静态成员之前初始化。
非最终静态成员按出现顺序初始化
因此,在您的第一种情况下:
static Test t=new Test(); static int a=5;
在初始化之前首先调用构造函数,因此显示a=0
。
在第二种情况下, static final a
在t
之前初始化,因此a=5
创建Test
的第一个实例时会显示a=5
。 当a
不是静态时,它会在执行构造函数之前初始化,因此再次显示a=5
。
关于你的问题的编辑。
查看JLS的第12.4.2节:
- 然后,初始化最终的类变量和接口字段,其值为编译时常量表达式 (§8.3.2.1,§9.3.1,§13.4.9,§15.28)。
…
- 接下来,按文本顺序执行类的类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。
您会看到最终的类变量(即静态final)只有在其值为编译时常量表达式时才会在其余静态变量之前初始化。 5
是常数表达式。 new Test()
不是。 因此,即使两者都是静态最终, a
也会在t
之前初始化。
当类加载器加载类时,静态变量被初始化。 因此,当第一行“静态测试t =新测试();”执行时,int“a”的值尚未初始化,因此它显示为0.但是其他3种情况(即删除静态,添加最终或没有任何修饰符)在对象创建Test类时初始化的内容发生了什么,它发生在第一行,因此显示值“5”。
Java语言规范是了解所有初始化顺序的最佳来源。 根据您的场景中的情况, static final
字段在任何类级别变量初始化之前初始化。 删除最终结果后,初始化被推迟。 如果你改变,也应该注意
static Test t=new Test(); static int a=5;
至
static int a=5; static Test t=new Test();
它也会打印
a = 5 a = 5
因为初始化顺序。
static final a=5
这是final
所以它首先在其他静态成员或方法之前初始化。
在第一个场景中, main()
方法首先执行,并将a
初始化为其默认值0
。