首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java多態與實例化:父類引用指向子類對象的核心機制解析

     編輯:程式設計綜合問答

代碼中`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`✅ 安全,運行時檢查通過✅ 無需轉型

為什麼要用父類引用?

  1. 多態參數/返回值:方法接收`List`實為`ArrayList`/`LinkedList`,返回`Collection`實為`HashSet`,解耦具體實現。
  2. 集合存儲異構對象:`List` 存 `Dog`、`Cat`,統一調用`makeSound()`。
  3. 依賴倒置原則**:高層模塊依賴抽象(`AA`),低層實現(`BB`),替換實現無需修改高層代碼。
  4. 工廠模式/策略模式**:工廠返回接口類型,隱藏具體類。

抽象類實例化規則

  • ❌ `new AA()` — 抽象類不能實例化(含抽象方法)。
  • ✅ `new BB()` — 具體子類實例化。
  • ✅ `AA aa = new BB();` — 父類引用指向子類對象,**多態基石**。
  • ✅ 匿名內部類:`AA aa = new AA() { void callMe() {...} };` — 即時實現抽象方法並實例化。

最佳實踐

  • 面向接口/抽象類編程:變量聲明、參數、返回值盡量用父類型。
  • 僅在需要子類特有成員時使用子類引用或強轉。
  • 避免字段遮蔽**:父子類同名字段導致引用類型決定訪問哪個,極易出錯,嚴禁同名字段。
  • 理解靜態方法不參與多態**:`static`方法調用由編譯時類型決定(靜態綁定)。
多態核心:引用類型定契約,對象類型定行為。父類引用指向子類對象,是面向對象設計解耦的基石。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved