Java静态最终字段初始化顺序

时间:2015-01-09 11:20:52

标签: java constructor static final static-members

当尝试使用对同一个封闭类对象的引用初始化静态字段时,我试图理解初始化顺序的行为。

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

为什么会出现这种情况?

请注意,即使两个a=5 & a=5都声明为t & astatic final输出也是ta

4 个答案:

答案 0 :(得分:3)

静态最终成员在其他静态成员之前初始化。

非最终静态成员按外观顺序初始化

因此,在您的第一个案例中:

    static Test t=new Test();
    static int a=5;

a初始化之前首先调用构造函数,因此显示a=0

在第二种情况下,static final at之前初始化,因此在创建a=5的第一个实例时会显示Test。如果a不是静态的,则会在执行构造函数之前对其进行初始化,因此会再次显示a=5

关于你问题的编辑。

查看12.4.2 of the JLS部分:

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

    ...

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

您会看到最终的类变量(即static final)仅在其值为编译时constant expressions之前在其余静态变量之前初始化。 5是一个常量表达式。 new Test()不是。因此a会在t之前初始化,即使两者都是静态最终结果。

答案 1 :(得分:1)

当类加载器加载类时,静态变量被初始化。因此,当第一行“静态测试t =新测试();”执行时,int“a”的值尚未初始化,因此它显示为0.但是其他3种情况(即删除静态,添加最终或没有任何修饰符)在创建Test类的Object时初始化会发生什么,这发生在第一行,因此它显示值“5”。

答案 2 :(得分:1)

Java Language specification是了解初始化顺序的最佳来源。根据您的方案中的情况,static final字段在任何类级别变量初始化之前初始化。删除最终结果后,初始化被推迟。如果你改变了

,也应该注意
static Test t=new Test();
static int a=5;

  static int a=5;
  static Test t=new Test();

它也会打印

 a = 5
 a = 5

因为初始化顺序。

答案 3 :(得分:0)

static final a=5它是final所以它首先在其他静态成员或方法之前初始化。

在第一个方案main()方法首先执行,并将a初始化为其默认值0