1.什麼是初始化
在Java中,一個對象在可以被使用之前必須要被正確地初始化,這一點是Java規範規定的。
類初始化階段是類加載過程的最後階段。在這個階段,java虛擬機才真正開始執行類定義中的java程序代碼。Java虛擬機是怎麼完成初始化的呢?這要從編譯開始講起。在編譯的時候,編譯器會自動收集類中的所有靜態變量(類變量)和靜態語句塊(static{}塊)中的語句合併產生的,編譯器收集的順序是根據語句在java代碼中的順序決定的。收集完成之後,會編譯成java類的 static{} 方法,java虛擬機則會保證一個類的static{} 方法在多線程或者單線程環境中正確的執行,並且只執行一次。在執行的過程中,便完成了類變量的初始化。值得說明的是,如果我們的java類中,沒有顯式聲明static{}塊,如果類中有靜態變量,編譯器會默認給我們生成一個static{}方法
2.對象初始化的順序
有兩個3個類代碼如下:
//A類
public class A {
private String name; //A1
private static C c =new C("A1"); //A2
static { //A3
System.out.println("A static 初始化");
}
{ //A4
System.out.println("A 普通代碼塊初始化");
}
public A() { //A5
System.out.println("A 構造方法初始化");
}
private C c2 = new C("A2"); //A6
}
//B類 是A的子類
public class B extends A{
private int age; //B1
static { //B2
System.out.println("B 的static 代碼塊初始化");
}
private static C c =new C("B1"); //B3
public B() { //B4
System.out.println("B 的構造方法初始化");
}
private C c2 = new C("B2"); //B5
{ //B6
System.out.println("B 的普通代碼塊初始化");
}
}
//C類 是AB類的一個組合
public class C {
public C (String index ) {
System.out.println( index+ "屬性初始化");
}
}
//test類
public class Test {
public static void main(String[]args) {
B b = new B();
}
}
//輸出結果
A1屬性初始化
A static 初始化
B 的static 代碼塊初始化
B1屬性初始化
A 普通代碼塊初始化
A2屬性初始化
A 構造方法初始化
B 的普通代碼塊初始化
B2屬性初始化
B 的構造方法初始化
由測試的輸出結果來看大致順序是
先靜態—-再普通 —-後構造函數
2.1先靜態
靜態可以分爲靜態屬性 與靜態代碼塊
由//A2 靜態屬性前//A3靜態代碼塊後 和//B2靜態代碼塊前 //B3 靜態屬性後這兩種情況的結果可以 推測 靜態屬性與靜態代碼塊的 初始化順序根據其定義的順序來
2.2再普通
普通也分爲普通的屬性與普通代碼塊
由//A4普通代碼塊前//A6普通屬性後 和 //B5普通屬性前//B6普通代碼塊後這兩種情況的輸出結果 推測 普通代碼塊與普通屬性的初始化順序根據其定義的順序來的
2.3後構造函數
構造函數情況可以分爲父類的構造函數,子類的構造函數
由輸出結果可推測 父類的構造函數先初始化 再子類的構造函數初始化
3.初始化規則總結
先靜態成員初始化 並且是按定義的順序來初始化的
再父類的普通成員 並且是按定義的順序來初始化的 ==》父類的構造函數
後子類的普通成員 並且是按定義的順序來初始化的 ==》子類的構造函數