java中具有繼承關係的類及其對象初始化順序

先說結論
對於具有繼承關係的類,它們的類和對象構造順序爲:父類的類構造器() -> 子類的類構造器() -> 父類成員變量的賦值和實例代碼塊 -> 父類的構造函數 -> 子類成員變量的賦值和實例代碼塊 -> 子類的構造函數。

實驗代碼如下:

public class ExtensionTest {

    public static void main(String[] args) {
        new SubClass();
    }
}

class SuperClass
{
    {
        System.out.println("我是父類實例塊");
    }
    static {
        System.out.println("我是父類類構造塊");
    }
    public SuperClass()
    {
        System.out.println("我是父類構造函數塊");
    }
}
class SubClass extends SuperClass
{
    {
        System.out.println("我是子類實例塊");
    }
    static {
        System.out.println("我是子類類構造塊");
    }
    public SubClass()
    {
        System.out.println("我是子類構造函數塊");
    }

}

結果:

我是父類類構造塊
我是子類類構造塊
我是父類實例塊
我是父類構造函數塊
我是子類實例塊
我是子類構造函數塊

解釋:
類構造塊是初始化類的時候執行的,而初始化類首先得加載類(不加載類進內存當然沒法初始化)。
類實例塊是放在該類構造函數最前面和父類構造函數之後執行的。因爲子類的構造函數調用之前,會先調用父類的構造函數。

基於上述兩條規則,我們再來看執行順序。
new SubClass()也就是要構造SubClass這個類的一個對象,而要構造這個對象,首先必須把這個類的描述、定義加載進內存(類加載)。因此要先加載這個類(不過此時還未初始化)。
加載完這個類之後,想要構造這個類的對象。但是此時這個類的靜態變量還未被初始化,因此要先初始化這個類,但是初始化這個類需要先初始化它的父類,因此此時就變成了,加載父類->初始化父類(調用靜態塊,即類構造塊)
->初始化子類(調用靜態塊,即類構造塊)。
然後就可以構造這個類的對象了,構造這個類的對象之前,要先構造父類對象,因此會先調用父類的構造函數,而調用父類構造函數之前又會先調用父類的實例塊。
然後就到了子類構造函數,然而執行之前一樣要先調用子類的實例塊,最後纔是子類的構造函數的函數體。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章