理解 Java 物件初始化順序與建構子鏈結是撰寫正確繼承體系的基石。本文梳理從類載入到實例化的完整流程,並以兩個對比範例說明 super() 顯式調用與預設調用的差異。
super(...) 或 this(...)),否則編譯器自動插入 super()。super(...),否則編譯錯誤。super() 僅能出現在建構子第一行,不能在方法或區塊中使用。Example 1:子類建構子顯式調用 super(x, y)
class Father {
int x = 0, y = 0;
Father() { System.out.println("Father 無參建構子"); }
Father(int x, int y) { this.x = x; this.y = y; }
void print() { System.out.println("x=" + x + "; y=" + y); }
}
class Son extends Father {
Son() { System.out.println("Son 無參建構子"); }
Son(int x, int y) { super(x, y); } // 顯式調用父類帶參建構子
void print() { super.print(); System.out.println("I am Son"); }
}
public class Example1 {
public static void main(String[] args) {
Son s1 = new Son(); // 輸出: Father無參 -> Son無參
s1.print(); // x=0; y=0 -> I am Son
Son s2 = new Son(10,20); // 輸出: Father(10,20) -> Son(10,20)
s2.print(); // x=10; y=20 -> I am Son
}
}
Example 2:子類建構子未顯式調用 super(x, y)
class Son extends Father {
Son(int x, int y) { System.out.println("s213"); } // 無 super(x,y),預設調用 super()
void print() { System.out.println("I am Son"); } // 未調用 super.print()
}
public class Example2 {
public static void main(String[] args) {
Son s1 = new Son(); // Father無參 -> Son無參
s1.print(); // I am Son
Son s2 = new Son(10,20); // Father無參 -> s213 (x,y 仍為 0)
s2.print(); // I am Son
}
}
關鍵差異: Example 1 中 Son(int,int) 透過 super(x,y) 初始化父類欄位,Example 2 則只執行父類無參建構子,導致 x,y 保持預設值 0。這證明:子類建構子預設調用父類無參建構子;若需傳參初始化父類狀態,必須顯式寫 super(...)。
super(...)。