| 成員 | 語法 | 執行時機 | 執行次數 |
|---|---|---|---|
| 靜態變數 | static int a = 1; | 類載入時 | 一次 |
| 靜態初始化塊 | static { ... } | 類載入時,按聲明順序 | 一次 |
| 實例變數 | int b = 2; | 建立物件時,在構造函數前 | 每次 new |
| 實例初始化塊 | { ... } | 建立物件時,按聲明順序,在構造函數前 | 每次 new |
| 構造函數 | public Class() {} | 建立物件時,最後執行 | 每次 new |
public class OrderTest {
static String sVar = "靜態變數";
String iVar = "實例變數";
static { System.out.println(sVar); System.out.println("靜態塊"); }
{ System.out.println(iVar); System.out.println("實例塊"); }
public OrderTest() { System.out.println("構造函數"); }
public static void main(String[] args) { new OrderTest(); }
}
// 輸出:
// 靜態變數
// 靜態塊
// 實例變數
// 實例塊
// 構造函數
規律:(靜態變數、靜態塊) > (實例變數、實例塊) > 構造函數。同類別內按「自上而下」聲明順序執行。
main 或觸發子類載入的邏輯父類--靜態變量
父類--靜態初始化塊
子類--靜態變量
子類--靜態初始化塊
子類main方法
父類--變量
父類--初始化塊
父類--構造器
i=9, j=0
子類--變量
子類--初始化塊
子類--構造器
i=9,j=20
注意:子類靜態成員初始化在父類實例成員之前完成。父類構造函數執行時,子類實例變數尚未初始化(預設值),這在多態調用時極易踩坑。
類載入階段: 父靜態 → 子靜態
實例化階段: 父實例變數/塊 → 父構造 → 子實例變數/塊 → 子構造
記住口訣:靜態先行,父前子後,塊前構後。