为什么字段似乎在构造函数之前被初始化?

Cha*_*hao 23 java output

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);
}
}
Run Code Online (Sandbox Code Playgroud)

输出是 -5

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

为什么这个订单是这样的?

Jas*_*key 21

如果你最后移动你的狗实例,你可能会发现输出变为-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
    }
}
Run Code Online (Sandbox Code Playgroud)

最终字段(其值为编译时常量表达式)将首先初始化,然后其余字段将以文本顺序执行.

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

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:

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


gkn*_*ker 10

变量声明序列.首先static final int val1进行初始化,因为它是常量.但是当时static int val2仍然是实例化的.0public static Dog dog = new Dog();


The*_*ind 6

怎么了..

正在执行的第一行是这个public static Dog dog = new Dog();.现在,必须牢记两件事.

  1. final int使它成为编译时常量.因此,-5已经硬编码到您的代码中.

  2. Dog()完成对new的调用并调用构造函数,将值设置为0+ -5= -5.

改变val2final那时你会看到差异(你会得到-2答案.)

注意:静态字段初始化为以及如何遇到它们.