Java初始化順序
1 無繼承情況下的Java初始化順序:
class Sample
{
Sample(String s)
{
System.out.println(s);
}
Sample()
System.out.println("Sample預設構造函數被調用");
}
class Test{
static Sample sam=new Sample("靜态成員sam初始化");
Sample sam1=new Sample("sam1成員初始化");
static{
System.out.println("static塊執行");
if(sam==null)System.out.println("sam is null");
sam=new Sample("靜态塊内初始化sam成員變量");
}
Test()
System.out.println("Test預設構造函數被調用");
//主函數
public static void main(String str[])
Test a=new Test();
}
輸出結果為:
靜态成員sam初始化 -----靜态成員初始化
static塊執行 -----靜态塊被執行
靜态塊内初始化sam成員變量 ----靜态塊執行
sam1成員初始化 -----普通成員初始化
Test預設構造函數被調用 -----構造函數執行
由此可以得出結論:
a 靜态成員變量首先初始化(注意,Static可以看做一個靜态成員,其執行順序和其在類中申明的順序有關)
b 普通成員初始化
c 執行構造函數。
對于靜态成員(static塊可以看成普通的一個靜态成員,其并不一定在類初始化時首先執行)和普通成員,其初始化順序隻與其在類定義中的順序有關,和其他因素無關。
例如下面的例子:
System.out.println("static 塊 1 執行");
static Sample staticSam1=new Sample("靜态成員staticSam1初始化");
static Sample staticSam2=new Sample("靜态成員staticSam2初始化");
System.out.println("static 塊 2 執行");
Sample sam2=new Sample("sam2成員初始化");
則結果為:
static 塊 1 執行
靜态成員staticSam1初始化
靜态成員staticSam2初始化
static 塊 2 執行
--------靜态成員
sam1成員初始化
sam2成員初始化
--------普通成員
Test預設構造函數被調用
--------構造函數
2 Java繼承情況下的初始化順序:
System.out.println("父類static 塊 1 執行");
static Sample staticSam1=new Sample("父類 靜态成員staticSam1初始化");
Sample sam1=new Sample("父類 sam1成員初始化");
static Sample staticSam2=new Sample("父類 靜态成員staticSam2初始化");
System.out.println("父類 static 塊 2 執行");
System.out.println("父類 Test預設構造函數被調用");
Sample sam2=new Sample("父類 sam2成員初始化");
class TestSub extends Test
static Sample staticSamSub=new Sample("子類 靜态成員staticSamSub初始化");
TestSub()
System.out.println("子類 TestSub 預設構造函數被調用");
Sample sam1=new Sample("子類 sam1成員初始化");
static Sample staticSamSub1=new Sample("子類 靜态成員staticSamSub1初始化");
static{System.out.println("子類 static 塊 執行");}
Sample sam2=new Sample("子類 sam2成員初始化");
執行結果:
父類 static 塊 1 執行
父類 靜态成員staticSam1初始化
父類 靜态成員staticSam2初始化
父類 static 塊 2 執行
--------父類靜态成員初始化
子類 靜态成員staticSamSub初始化
子類 靜态成員staticSamSub1初始化
子類 static 塊 執行
-------子類靜态成員初始化
父類 sam1成員初始化
父類 sam2成員初始化
父類 Test預設構造函數被調用
-------父類普通成員初始化和構造函數執行
子類 sam1成員初始化
子類 sam2成員初始化
子類 TestSub 預設構造函數被調用
由此得出Java初始化順序結論:
1 繼承體系的所有靜态成員初始化(先父類,後子類)
2 父類初始化完成(普通成員的初始化-->構造函數的調用)
3 子類初始化(普通成員-->構造函數)
Java初始化順序如圖:

有的朋友問到内部的機制,上述的初始化順序是由下面的幾條規則決定的:
1.首先初始化靜态域是因為靜态域是放在方法區和class對象在一起的。
2.由于類加載的時候,會向上查找基類,因為子類的初始化依賴于基類首先初始化。是以會首先發生“基類->子類"順序的類加載,類加載過程中,順便完成了靜态域的初始化。
3.另外一條規則是初始化塊優先于域的初始化(靜态和非靜态分别是如此)。
詳見thinking in java中譯本第四版的P147頁。
轉自:http://www.cnblogs.com/miniwiki/archive/2011/03/25/1995615.html