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();
    }
}
InitialOrderTest.class

 

運行以上代碼,我們會得到如下的輸出結果:
1. 靜態變量
2. 靜態初始化塊
3. 變量
4. 初始化塊
5. 構造器

 

這與上文中說的完全符合。那么對於繼承情況下又會怎樣呢?我們仍然以一段測試代碼來獲取最終結果:

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;
     }
}
Parent.class
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();
     }
}
SubClass.class

運行一下上面的代碼,結果如下:
父類--靜態變量
父類--靜態初始化塊
子類--靜態變量
子類--靜態初始化塊
子類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來指定調用哪個構造函數(也就是Beetle()構造函數所做的第一件事)。
基類的構造過程以及構造順序,同派生類的相同。首先基類中各個變量按照字面順序進行初始化,然后執行基類的構造函數的其余部分。

(5)對子類成員數據按照它們聲明的順序初始化,執行子類構造函數的其余部分。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM