先看看下面的這段代碼,這個例子將說明類載入的順序。也可以直接略過代碼,直接看下面的圖:
class GrandFather{GrandFather(){System.out.println("the GrandFather constructor is initialized");}static{System.out.println("the GrandFather static filed is initialized");}}class Father extends GrandFather{Father(){System.out.println("the Father constructor is initialized!");}static{System.out.println("the Father static filed is initialized");}}public class Son extends Father {public Son(){System.out.println("the Son constructor is initialized");}static{System.out.println("the Son static filed is initialized");}public static void main(String[] args) {Son son = new Son();}}為了更直觀的說明,將上面的代碼轉化成下面的圖:
將上面的代碼運行,得出的結果是:
the GrandFather static filed is initializedthe Father static filed is initializedthe Son static filed id initializedthe GrandFather constructor is initializedthe Father constructor is initialized!the Son constructor is initialized
怎麼樣,看了上面的運行結果,心裡是不是有點小感覺了已經?下面用文字總結下:1,在Son上運行java時,第一件事情就是試圖訪問Son的main方法(一個static方法)。於是載入器開始啟動並找出Son類的編譯代碼(在名為Son.class的檔案中)。2,在對Son類進行載入的過程中,編譯器注意到它有個基類(這是又關鍵字extends知道的),這裡為Father,於是繼續載入Father類。如果該基類還有其自身的基類,這裡有個GrandFather類,於是GrandFather也被載入。如此類推。3,接下來,根基類中static(包括static方法,變數,域)初始化,然後是下一個匯出類,以此類推。這裡static初始化的順序是GrandFather>Father>Son。至於為什麼要從根基類開始初始化,不難想到是因為 匯出類的static初始化可能依賴於基類成員能否被正確初始化。4,經過上面幾步,必要的類都載入完畢,對象就可以被建立了。 a,首先,對象中所有的基本類型都會被設為預設值,對象引用被設為NULL(對於這一點,再看看下面給出的例子) b,然後,基類的構造器會被調用 c,最後,構造器的其餘部分被調用
public class Test{ /** * @param args */ private int i=getValue();//第2行 private int j = 10; int getValue(){ return j; } public static void main(String[] args) { System.out.print(new Test().i);//第9行 }}
很顯然,這個例子在執行到上面的第4步時,只執行了a,b兩步,而第三步 private int j = 10,在i被調用時還沒被執行