代碼中`AA aa = new BB();`與`BB aa = new BB();`編譯後調用`aa.callMe()`/`aa.meToo()`行為不同,本質是編譯時類型(引用類型)決定可見成員,運行時類型(對象實際類型)決定方法實現。本文深度解析多態機制。
abstract class AA {
abstract void callMe();
void meToo() { System.out.println("AA meToo"); }
}
class BB extends AA {
void callMe() { System.out.println("BB callMe"); }
void meToo() { System.out.println("BB meToo"); } // 覆寫
}
public class Test {
public static void main(String[] args) {
AA aa1 = new BB(); // 父類引用
BB aa2 = new BB(); // 子類引用
aa1.callMe(); // BB callMe (動態綁定)
aa1.meToo(); // BB meToo (動態綁定)
aa2.callMe(); // BB callMe
aa2.meToo(); // BB meToo
}
}
**輸出完全相同**,因為兩個引用指向同一`BB`對象,**非靜態方法調用均為動態分派**。
| 場景 | `AA aa = new BB()` | `BB aa = new BB()` |
|---|---|---|
| 調用 `aa.callMe()` | ✅ `AA`聲明了抽象方法 | ✅ |
| 調用 `aa.meToo()` | ✅ `AA`有此方法 | ✅ |
| 調用 `aa.bbOnlyMethod()` | ❌ 編譯錯誤:`AA`無此方法 | ✅ |
| 訪問 `aa.bbOnlyField` | ❌ 編譯錯誤 | ✅ |
| 強制轉型 `(BB)aa` | ✅ 安全,運行時檢查通過 | ✅ 無需轉型 |
多態核心:引用類型定契約,對象類型定行為。父類引用指向子類對象,是面向對象設計解耦的基石。