Java 內部類持有對外部類實例的隱式引用,這導致繼承內部類時必須在子類構造器中顯式傳遞外部類實例並調用 外部實例.super()。這與普通類繼承僅需 super() 形成鮮明對比,是許多開發者的困惑來源。
class WithInner {
class Inner {} // 非靜態內部類
}
public class InheritInner extends WithInner.Inner {
// 必須接收外部類實例並傳給 super()
InheritInner(WithInner wi) {
wi.super(); // 關鍵語法:外部實例.super()
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi); // 傳入外部實例
System.out.println("繼承成功: " + ii.getClass().getSimpleName());
}
}
若內部類定義了帶參構造器,子類構造器必須透過 外部實例.super(參數) 傳遞參數:
class WithInner {
class Inner {
public Inner(int i) {
System.out.println("Inner 構造器參數: " + i);
}
}
}
public class InheritInner extends WithInner.Inner {
InheritInner(WithInner wi) {
wi.super(42); // 傳遞參數給內部類構造器
}
public static void main(String[] args) {
new InheritInner(new WithInner()); // 輸出: Inner 構造器參數: 42
}
}
wi.super() 轉換為調用內部類構造器並傳入 wi 作為 this$0 隱藏參數。| 錯誤代碼 | 問題 | 正確寫法 |
|---|---|---|
super(); |
嘗試調用 Object 構造器,缺少外部實例引用 | outerInstance.super(); |
new InheritInner() |
無參構造器無法提供外部實例 | new InheritInner(new Outer()) |
繼承靜態內部類時用 outer.super() |
靜態內部類不持有外部引用,無需此語法 | 直接 extends Outer.StaticInner { ... } |
static class 可避免繼承複雜性。Java 內部類繼承語法 outerInstance.super(...) 雖顯晦澀,但深刻體現了「內部類實例依附於外部類實例」的運行時語義。理解其底層機制(隱藏的 this$0 引用),能幫助開發者在複雜類結構中做出正確設計決策。實際項目中,能用靜態內部類或組合模式解決的,盡量避免繼承非靜態內部類。