为什么字段似乎在构造函数之前初始化?更新了较新的文档

2022-09-01 22:39:28
public class Dog {

 public static Dog dog = new Dog();
 static final int val1 = -5;
 static int val2 = 3;
 public int val3;

 public Dog() {
      val3 = val1 + val2;
 }

public static void main(String[] args) {
    System.out.println(Dog.dog.val3);
}
}

输出为-5

从这个结果来看,初始化 似乎是在成员完成及其实例化之前。val2dog

为什么这个顺序是这样的?


答案 1

如果你最终移动你的狗实例,你可能会发现输出变成-2

public class Dog {

     static final int val1 = -5;// This is final, so will be initialized at compile time 
     static int val2 = 3;
     public int val3;

     public static Dog dog = new Dog();//move to here
 
     public Dog() {
          val3 = val1 + val2;
     }

    public static void main(String[] args) {
        System.out.println(Dog.dog.val3);//output will be -2
    }
}

最后的字段(其值是编译时常量表达式)将首先初始化,然后其余字段将按文本顺序执行。

因此,在你的情况下,当dog实例初始化时,(0)尚未初始化,而(-5)则初始化,因为它是最终的。static int val2static final int val1

http://docs.oracle.com/javase/specs/jls/se5.0/html/execution.html#12.4.2 指出:

文本顺序执行类的类变量初始值设定项和静态初始值设定项,或执行接口的字段初始值设定项,就好像它们是单个块一样,除了最终类变量和值为编译时常量的接口的字段首先初始化


更新了较新的文档

这是来自 http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2 jdk7版本

最终字段位于步骤 6:

然后,初始化最终的类变量和接口的字段,其值为编译时常量表达式

而静态字段位于步骤 9:

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


答案 2

变量声明序列。首先初始化 ,因为它是一个常量。然而,当时仍在实例化。static final int val1static int val20public static Dog dog = new Dog();


推荐