代碼片段
static void show(A b) { b.add(8); b.print(); }
public static void main(String[] args) { show(new AA()); }
執行流程
- `main` 中 `new AA()` 創建子類對象,構造鏈:
`AA()` → `super()` → `A()` → `add(1)` → `A.add(1)` → `i=1` → 返回 `AA()` → `add(2)` → `AA.add(2)` → `i=1+4=5`。
- `show(new AA())` 參數 `b` 靜態類型 `A`,動態類型 `AA`。
- `b.add(8)` → 動態分派調用 `AA.add(8)` → `i=5+16=21`。
- `b.print()` → `A.print()`(未重寫)輸出 `21`。
(若 `AA` 重寫 `print` 則調用子類版本)
關鍵概念
- 動態綁定:非 static、非 private、非 final 方法,運行時根據對象實際類型分派。
- 構造器中調用可重寫方法危險:父類構造器執行時子類字段未初始化,若子類重寫方法依賴字段會見到默認值(0/null)。
- show 方法參數:`A b` 是形式參數,接收實參 `new AA()` 的引用,多態生效前提。
輸出 22 還是 21?
題目輸出 22 可能 `AA.add` 邏輯為 `i += v*2`,`A.add` 為 `i += v`。構造鏈:`A()` add(1)→i=1;`AA()` add(2)→i=1+4=5;`show` add(8)→i=5+16=21。若 `AA` 構造器額外 `add(1)` 或 `A()` 兩次 `add` 則得 22。具體以代碼為準。