關於類方法塊的調用順序,一直沒有進行總結記錄過,中午趁着午飯時間,稍微溫習下最基礎的內容,並記錄下。
靜態代碼塊、普通代碼塊、構造函數塊:

1 public class Test { 2 3 public static void main(String[] args) { 4 5 new Square(); 6 System.out.println("--------Next---------"); 7 new Circle(); 8 9 } 10 } 11 class Shape { 12 13 public Shape() { 14 System.out.println("Shape Constructor."); 15 } 16 17 static { 18 System.out.println("Shape static code."); 19 } 20 21 { 22 System.out.println("Shape normal code."); 23 } 24 25 } 26 class Square extends Shape{ 27 28 public Square() { 29 System.out.println("Square Constructor."); 30 } 31 32 static { 33 System.out.println("Square static code."); 34 } 35 36 { 37 System.out.println("Square normal code."); 38 } 39 40 } 41 class Circle extends Shape { 42 43 public Circle() { 44 System.out.println("Circle Constructor."); 45 } 46 47 static { 48 System.out.println("Circle static code."); 49 } 50 51 { 52 System.out.println("Circle normal code."); 53 } 54 55 }
從輸出結果發現, 在創建一個對象的時候, 會發生如下的過程:
父類未被加載過:
- 父類是否被加載過, 沒有加載則進行加載, 父類靜態代碼塊隨之調用
- 加載子類, 子類靜態代碼塊隨之調用
- 調用父類的普通代碼塊
- 調用父類的構造方法
- 調用子類的普通代碼塊
- 調用子類的構造方法
-----------------Next------------------------
父類已經被加載過:
- 加載子類, 子類靜態代碼塊隨之調用
- 調用父類的普通代碼塊
- 調用父類的構造方法
- 調用子類的普通代碼塊
- 調用子類的構造方法
注意:
在子類的構造方法中, super()必須先被調用, 若沒有寫, 運行時會自動調用super()方法;
如果父類沒有無參構造方法, 需要手動進行super()的調用。
總結:
在子類構造方法中, 不管是手動調用父類構造方法還是運行時自動調用, 必須滿足:
1. 子類的構造方法必須先調用父類中的某個構造方法;
2. 被子類調用的父類構造方法在父類中必須是存在的.
通過反編譯class文件, 會發現其實普通代碼塊的代碼被合並到構造方法中了,在構造方法的內的最上部,所以出現上面普通代碼塊在構造方法前執行的結果。
另外編碼時需要注意一點:因為靜態變量和靜態代碼塊的執行順序是根據代碼編寫的順序進行執行的,所以靜態變量要定義在靜態代碼塊的前面。