jvm系列學習之--Java類的初始化順序
本文主要演示Java類的初始化順序
初始化順序
對於靜態變量、靜態初始化塊、變量、初始化塊、構造器,它們的初始化順序依次是(靜態變量、靜態初始化塊)>(變量、初始化塊)>構造器。
實例代碼
public class InitialOrderTest { /* 靜態變量 */ public static String staticField = "靜態變量"; /* 變量 */ public String field = "變量"; /* 靜態初始化塊 */ static { System.out.println( staticField ); System.out.println( "靜態初始化塊" ); } /* 初始化塊 */ { System.out.println( field ); System.out.println( "初始化塊" ); } /* 構造器 */ public InitialOrderTest() { System.out.println( "構造器" ); } public static void main( String[] args ) { new InitialOrderTest(); } }
輸出
運行以上代碼,我們會得到如下的輸出結果:
-
靜態變量
-
靜態初始化塊
-
變量
-
初始化塊
-
構造器
繼承的情況
實例代碼
class Parent { /* 靜態變量 */ public static String p_StaticField = "父類--靜態變量"; /* 變量 */ public String p_Field = "父類--變量"; protected int i = 9; protected int j = 0; /* 靜態初始化塊 */ static { System.out.println( p_StaticField ); System.out.println( "父類--靜態初始化塊" ); } /* 初始化塊 */ { System.out.println( p_Field ); System.out.println( "父類--初始化塊" ); } /* 構造器 */ public Parent() { System.out.println( "父類--構造器" ); System.out.println( "i=" + i + ", j=" + j ); j = 20; } } public class SubClass extends Parent { /* 靜態變量 */ public static String s_StaticField = "子類--靜態變量"; /* 變量 */ public String s_Field = "子類--變量"; /* 靜態初始化塊 */ static { System.out.println( s_StaticField ); System.out.println( "子類--靜態初始化塊" ); } /* 初始化塊 */ { System.out.println( s_Field ); System.out.println( "子類--初始化塊" ); } /* 構造器 */ public SubClass() { System.out.println( "子類--構造器" ); System.out.println( "i=" + i + ",j=" + j ); } /* 程序入口 */ public static void main( String[] args ) { System.out.println( "子類main方法" ); new SubClass(); } }
輸出
父類--靜態變量
父類--靜態初始化塊
子類--靜態變量
子類--靜態初始化塊
子類main方法
父類--變量
父類--初始化塊
父類--構造器
i=9, j=0
子類--變量
子類--初始化塊
子類--構造器
i=9,j=20
子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。靜態變量、靜態初始化塊,變量、初始化塊初始化了順序取決於它們在類中出現的先後順序。
分析
-
(1)訪問SubClass.main(),(這是一個static方法),於是裝載器就會為你尋找已經編譯的SubClass類的代碼(也就是SubClass.class文件)。在裝載的過程中,裝載器註意到它有一個基類(也就是extends所要表示的意思),於是它再裝載基類。不管你創不創建基類對象,這個過程總會發生。如果基類還有基類,那麽第二個基類也會被裝載,依此類推。
-
(2)執行根基類的static初始化,然後是下一個派生類的static初始化,依此類推。這個順序非常重要,因為派生類的“static初始化”有可能要依賴基類成員的正確初始化。
-
(3)當所有必要的類都已經裝載結束,開始執行main()方法體,並用new SubClass()創建對象。
-
(4)類SubClass存在父類,則調用父類的構造函數,你可以使用super來指定調用哪個構造函數。基類的構造過程以及構造順序,同派生類的相同。首先基類中各個變量按照字面順序進行初始化,然後執行基類的構造函數的其余部分。
-
(5)對子類成員數據按照它們聲明的順序初始化,執行子類構造函數的其余部分。
jvm系列學習之--Java類的初始化順序