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();
怎么了..
正在执行的第一行是这个public static Dog dog = new Dog();.现在,必须牢记两件事.
final int使它成为编译时常量.因此,-5已经硬编码到您的代码中.
Dog()完成对new的调用并调用构造函数,将值设置为0+ -5= -5.
改变val2到final那时你会看到差异(你会得到-2答案.)
注意:静态字段初始化为以及如何遇到它们.