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

Java 繼承機制全解析:extends 關鍵字、方法覆蓋、protected 訪問、構造器鏈與組合復用原則對比

     編輯:Java 綜合教學

Java 繼承機制全解析:從 extends 關鍵字到組合優於繼承的工程智慧

繼承 是面向對象復用代碼的核心機制之一,但也是最容易被濫用、導致強耦合的特性。本文系統講解 extends 語法、衍生類對象內存佈局、protected 訪問控制、方法覆蓋、構造器鏈調用、super 與 this 語義、以及「組合優於繼承」設計原則對比,助你在正確場景下正確使用繼承。

1. 基礎語法:extends 關鍵字

class Human {
    private int height;
    public Human(int h) { this.height = h; }
    public int getHeight() { return height; }
    public void growHeight(int h) { height += h; }
    public void breath() { System.out.println("hu...hu..."); }
}

class Woman extends Human {  // 單繼承
    public Woman(int h) { super(h); } // 必須顯式調用父構造器
    public Human giveBirth() {
        System.out.println("Give birth");
        return new Human(20);
    }
    @Override
    public void breath() {
        super.breath(); // 調用父類實現
        System.out.println("su...");
    }
}

2. 衍生類對象內存佈局:三層訪問權限模型

┌─────────────────────────────────────┐
│         Woman Object (衍生類)        │
├─────────────────────────────────────┤
│  Human Part (基類對象 subobject)     │  ← super 引用此區域
│  ├─ private int height  (紅×××)     │  ← 衍生類不可訪問,外部不可訪問
│  ├─ public getHeight()  (綠✓)       │  ← 衍生類可訪問,外部可訪問
│  ├─ public breath()     (綠✓)       │  ← 可覆蓋
│  └─ ...                           │
├─────────────────────────────────────┤
│  Woman Part (衍生層)                 │  ← this 引用整個對象
│  ├─ public giveBirth()  (綠✓)       │  ← 衍生類新增
│  ├─ public breath()     (綠✓)       │  ← 覆蓋版本
│  └─ ...                           │
└─────────────────────────────────────┘
  • 基類對象先構建:new Woman() 先在堆上分配 Human 部分,再擴展 Woman 部分
  • 訪問權限:private 只在聲明類可見;protected 在聲明類 + 衍生類可見;public 普遍可見
  • super vs this:super 視圖僅含基類部分;this 視圖含完整衍生對象

3. protected 關鍵字:衍生類的專屬通道

class Base {
    protected int  protectedField = 1;
    private   int  privateField   = 2;
    public    int  publicField    = 3;
    protected void protectedMethod() {}
    private   void privateMethod()   {}
}

class Derived extends Base {
    void test() {
        System.out.println(protectedField); // ✅ 可訪問
        System.out.println(publicField);    // ✅ 可訪問
        // System.out.println(privateField); // ❌ 編譯錯誤
        protectedMethod(); // ✅ 可調用
        // privateMethod(); // ❌ 不可見
    }
}

設計意圖:封裝「衍生類需知、外部不可知」的內部實現細節。

4. 方法覆蓋:動態分派的核心規則

規則說明代碼示例
簽名相同方法名、參數列表、返回類型 (协变返回允許子類型)@Override 編譯器校驗
權限不降子類權限 ≥ 父類權限父 protected → 子 public ✅;父 public → 子 protected ❌
異常不增子類拋出異常 ⊆ 父類異常父 throws IOException → 子 throws FileNotFoundException ✅
不可覆蓋final/static/private/構造器final 鎖定實現,static 隱藏非覆蓋

5. 構造器鏈:super() 必須首行調用

class Human {
    private int height;
    public Human(int h) { this.height = h; System.out.println("Human init"); }
}

class Woman extends Human {
    private String name;
    public Woman(int h, String name) {
        super(h);                 // 必須第一行,且只能調用一次
        this.name = name;         // 衍生層字段初始化
        System.out.println("Woman init");
    }
}
// new Woman(160, "Alice") 輸出:
// Human init
// Woman init

機制:JVM 保證基類構造器先完成,衍生類字段才初始化。若父類無無參構造器,子類必須顯式 super(...)。

6. 繼承 vs 組合:核心對比與選擇指南

維度繼承組合
關係Is-A (是一種)Has-A (有一個)
耦合度強:子類依賴父類實現細節弱:依賴介面契約
封裝性破壞:protected 暴露內部保護:內部對象完全隱藏
靈活性編譯期靜態綁定運行期動態替換組件
多態天然支援需配合介面實現
構造順序父→子固定完全可控
適用場景「確實是」關係穩定、需複用父類邏輯、擴展點固定大多數復用場景、需動態行為、多組件組合

7. 經典反面教材:繼承濫用導致的災難

// ❌ 錯誤:Stack 繼承 Vector (Java 早期失誤)
// Stack 是 Vector 嗎?不是,Stack 是「棧」行為,Vector 是「動態數組」實現
// 導致 Stack 繼承了 Vector 所有 public 方法 (add/insert/removeAt 等),破壞棧語義
// 正確:Stack 組合 List/Deque 內部委派

// ❌ 錯誤:Properties 繼承 Hashtable
// Properties 是「鍵值配置」,Hashtable 是「同步雜湊表」
// 導致 Properties 可 put 非 String 鍵值,getProperty 卻只取 String
// 正確:Properties 組合 Map

8. 重構指南:繼承轉組合三步法

  1. 將父類提取為介面 interface Service
  2. 子類改為實現介面,持有 Service delegate 字段
  3. 原 super.method() 改為 delegate.method(),暴露需對外的方法

總結

extends 是強大的「Is-A」建模工具,但會產生強耦合、破壞封裝、固化層次。掌握 衍生類內存佈局、protected 語義、覆蓋規則、構造器鏈機制 是正確使用前提。工程實踐中 默認選擇組合,僅在「確實是穩定 Is-A 關係、需複用完整父類邏輯、擴展點固定」時使用繼承。記住 GoF 經典原則:Favor composition over inheritance。下一篇我們將深入 Java 介面默認方法與函數式介面新特性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved