[英]Why do fields seem to be initialized before constructor?
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
從這個結果來看,似乎val2
的初始化是在dog
成員完成之前及其實例化。
為什么這個訂單是這樣的?
如果你最后移動你的狗實例,你可能會發現輸出變為-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實例的情況下, static int val2
(0)尚未初始化,而static final int val1
(-5)因為它是final而執行。
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:
接下來,按文本順序執行類的類變量初始值設定項和類的靜態初始值設定項,或接口的字段初始值設定項,就好像它們是單個塊一樣。
變量聲明序列。 static final int val1
首先被初始化,因為它是一個常量。 但是static int val2
在public static Dog dog = new Dog();
時仍為0
public static Dog dog = new Dog();
被實例化。
怎么了..
正在執行的第一行是這個public static Dog dog = new Dog();
。 現在,必須牢記兩件事。
final int
使它成為編譯時常量。 因此, -5
已經硬編碼到您的代碼中。
完成對新Dog()
的調用並調用構造函數,將值設置為0
+ -5
= -5
。
將val2
更改為final
然后您將看到差異(您將得到-2
作為答案。)
注意:靜態字段初始化為以及如何遇到它們。
測試中的初始化順序;
static final int val1 = -5;
//常數為靜態最終 public static Dog dog = new Dog();
//然后'dog'初始化但其成員val2尚未初始化 static int val2 = 3;
//最后'val2'被初始化 此代碼更改將輸出-2
;
public class Dog {
//public static Dog dog = new Dog();
static final int val1 = -5;
static int val2 = 3;
public int val3;
public static Dog dog = new Dog(); //moved here
public Dog() {
val3 = val1 + val2;
}
public static void main(String[] args) {
System.out.println(Dog.dog.val3);
}
}
所有靜態變量都在一個單獨的靜態構造函數中初始化,該構造函數在類加載時執行。 與代碼中的apear順序相同。 你的例子被編譯成這樣的東西:
public class Dog {
public static Dog dog;
static final int val1 = -5;
static int val2;
public int val3;
static {
dog = new Dog();
val2 = 3;
}
public Dog() {
val3 = val1 + val2;
}
public static void main(String[] args) {
System.out.println(Dog.dog.val3);
}
}
這就是為什么類/實例變量的順序很重要的原因。 類構造函數執行在初始化結束時發生。 常數在之前得到解決。 有關更多信息,請參閱創建新類實例 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.