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 at之前初始化,因此a=5创建Test的第一个实例时会显示a=5 。 当a不是静态时,它会在执行构造函数之前初始化,因此再次显示a=5

关于你的问题的编辑。

查看JLS的第12.4.2节:

  1. 然后,初始化最终的类变量和接口字段,其值为编译时常量表达式 (§8.3.2.1,§9.3.1,§13.4.9,§15.28)。

  1. 接下来,按文本顺序执行类的类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。

您会看到最终的类变量(即静态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