先說結論
對於具備繼承關係的類,它們的類和對象構造順序爲:父類的類構造器() -> 子類的類構造器() -> 父類成員變量的賦值和實例代碼塊 -> 父類的構造函數 -> 子類成員變量的賦值和實例代碼塊 -> 子類的構造函數。函數
實驗代碼以下:code
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這個類的一個對象,而要構造這個對象,首先必須把這個類的描述、定義加載進內存(類加載)。所以要先加載這個類(不過此時還未初始化)。
加載完這個類以後,想要構造這個類的對象。可是此時這個類的靜態變量還未被初始化,所以要先初始化這個類,可是初始化這個類須要先初始化它的父類,所以此時就變成了,加載父類->初始化父類(調用靜態塊,即類構造塊)
->初始化子類(調用靜態塊,即類構造塊)。
而後就能夠構造這個類的對象了,構造這個類的對象以前,要先構造父類對象,所以會先調用父類的構造函數,而調用父類構造函數以前又會先調用父類的實例塊。
而後就到了子類構造函數,然而執行以前同樣要先調用子類的實例塊,最後纔是子類的構造函數的函數體。io