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

Java 繼承、抽象類、接口全維度解析:語法、設計模式、最佳實踐

     編輯:Java 綜合教學

Java 繼承、抽象類、接口全維度解析:語法、設計模式、最佳實踐

繼承、抽象類、接口構成 Java 物件導向設計的「鐵三角」。本文從語法規範、記憶體模型、設計原則、模式應用、演進特性 (Java 8/9/17+) 五個維度,系統構建完整知識體系。

一、繼承

1. 語法與核心規則

  • 關鍵字:extends,單繼承 (一個父類),多層繼承形成鏈
  • 繼承內容:非 private 欄位、方法、嵌套類;建構子、初始化塊不繼承 (但子類建構子必須調用父類建構子)
  • 訪問權限:public/protected 可見;private 不可見 (但透過 getter/setter 間接訪問);default 同包可見
  • Object 根類:所有類隱式繼承 Object,擁有 toString/equals/hashCode/clone/finalize/wait/notify/getClass

2. 建構子鏈與初始化順序

class Grandpa { 
    Grandpa() { System.out.println("Grandpa()"); } 
}
class Father extends Grandpa { 
    Father() { System.out.println("Father()"); } 
}
class Child extends Father { 
    Child() { System.out.println("Child()"); } 
}
// new Child() 輸出:
// Grandpa()
// Father()
// Child()

// 規則:隱式/顯式 super() 必須為建構子第一句 → 父類優先初始化 → 保證父類狀態就緒

3. 方法關係三態

關係定義例子
擴充子類新增父類無同名方法Father 無 fly(),Child 定義 fly()
覆寫同名、同參數、同返回類型 (或协变)、權限不降低、拋出異常不擴大@Override void show()
重載同名、參數列表不同 (類型/數量/順序)void print(int) / void print(String)

4. final 關鍵字與不可變模式

  • final class:不可繼承 (String、Integer、LocalDate)
  • final method:不可覆寫 (getClass、wait、Thread.run)
  • final field:引用不可變 (對象內部狀態仍可變),建構子初始化
  • 不可變類模式:final class + final fields + 無 setter + 防禦性複製 + 工廠方法

5. 多態與「+」運算符隱式 toString

Fruit f = new Apple();
System.out.println("Fruit: " + f); // 隱式調用 f.toString()
// 等價於
System.out.println("Fruit: " + String.valueOf(f)); // null 安全

二、抽象類

1. 核心規範

  • abstract class:不可實例化,可含抽象/非抽象方法、欄位、建構子、靜態方法、內部類
  • abstract method:無方法體,子類必須實現 (除非子類也 abstract)
  • 抽象類可 無抽象方法 (如 HttpServlet),強制被繼承
  • 建構子用於子類 super() 初始化父類狀態,不可被外部 new

2. 模板方法模式 (抽象類經典應用)

public abstract class DataProcessor {
    // final 鎖定演算法骨架
    public final void process() {
        readData();
        validate();
        transform();
        writeResult();
    }
    
    protected abstract void readData();
    protected abstract void transform();
    protected abstract void writeResult();
    
    // Hook 方法:預設空實現,子類可選擇性覆寫
    protected void validate() { }
    protected void beforeWrite() { }
}

public class CsvProcessor extends DataProcessor {
    @Override protected void readData() { /* CSV 讀取 */ }
    @Override protected void transform() { /* 轉換邏輯 */ }
    @Override protected void writeResult() { /* 寫入 DB */ }
    @Override protected void validate() { /* CSV 專屬校驗 */ }
}

三、接口

1. 語法演進史

版本新特性影響
Java 7-常量、抽象方法純契約,無實現
Java 8default 方法、static 方法、函數式介面 (@FunctionalInterface)默認實現、靜態工具、Lambda 基礎
Java 9private 方法、private static 方法default 方法間代碼復用、封裝
Java 17+sealed 介面 (許可實現類)受控繼承、模式匹配穩盡性檢查

2. 多實現與鑽石問題

interface A { default void foo() { System.out.println("A"); } }
interface B { default void foo() { System.out.println("B"); } }
class C implements A, B {
    // 必須顯式覆寫解決衝突
    @Override public void foo() { 
        A.super.foo(); // 顯式選擇調用 A 的默認實現
        // B.super.foo(); 
    }
}

3. 介面 vs 抽象類:選型決策樹

需要構建類別體系嗎?
  ├─ 是 → 需要共享狀態/代碼/建構子邏輯? → 抽象類
  │         ├─ 否 → 定義能力契約、多實現、插件化、函數式? → 介面
  │         └─ 兩者兼備 → 抽象類實現介面 (如 AbstractList implements List)
  └─ 否 → 工具類用 final class + static methods / 單例用 enum

4. 函數式介面與 Lambda

@FunctionalInterface
public interface Converter {
    T convert(F from);
    // 只能有一個抽象方法,default/static/Object 方法不計數
}

// 使用
Converter toInt = Integer::valueOf; // 方法引用
Converter toInt2 = s -> Integer.parseInt(s); // Lambda
Integer result = toInt.convert("123");

四、設計原則與最佳實踐

1. 里氏替換原則 (LSP)

  • 子類必須能替換父類而不破壞程式語義
  • 違反例:Square extends Rectangle (setWidth 影響 height),Penguin extends Bird (fly() 拋異常)
  • 修正:組合優於繼承、介面隔離 (Flyable、Swimmable)

2. 介面隔離原則 (ISP)

  • 介面應盡量小、專一,客戶端不依賴不需要的方法
  • 違反例:IMachine { print/scan/fax/email } → 拆分為 IPrinter、IScanner、IFax...

3. 依賴倒置原則 (DIP)

  • 高層模組不依賴低層模組,雙方依賴抽象 (介面/抽象類)
  • 實踐:Controller 依賴 Service 介面、Repository 依賴 DAO 介面、DI 容器注入實現

4. 組合優於繼承

// 繼承:強耦合、脆弱、單一維度
class Bird { void fly() {} }
class Penguin extends Bird { /* 不會飛 */ }

// 組合:靈活、多維度、運行期可變
interface FlyBehavior { void fly(); }
class FlyWithWings implements FlyBehavior { ... }
class FlyNoWay implements FlyBehavior { ... }

class Bird {
    private FlyBehavior flyBehavior;
    public void setFlyBehavior(FlyBehavior fb) { this.flyBehavior = fb; }
    public void performFly() { flyBehavior.fly(); }
}
// 策略模式:運行期動態切換飛行行為

五、Java 17+ 現代特性實戰

1. Sealed 類/介面 (受控繼承)

// 僅允許列出的類實現/繼承,編譯器強制檢查
public sealed interface Shape permits Circle, Rectangle, Triangle { }
public final class Circle implements Shape { ... }
public final class Rectangle implements Shape { ... }
public non-sealed class Triangle implements Shape { ... } // 可繼承

// 模式匹配 switch (JEP 441) 穩盡性檢查
public double area(Shape s) {
    return switch (s) {
        case Circle c -> Math.PI * c.radius() * c.radius();
        case Rectangle r -> r.width() * r.height();
        case Triangle t -> 0.5 * t.base() * t.height();
        // 無 default,編譯器保證覆蓋所有許可實現
    };
}

2. Record (不可變數據載體)

public record User(Long id, String name, String email) {
    // 自動生成:final fields、canonical constructor、getter、equals/hashCode、toString
    // 可添加驗證邏輯
    public User {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required");
        email = email.toLowerCase(); // 正規化
    }
}

六、總結

繼承提供「is-a」強關聯與代碼復用,抽象類鎖定演算法骨架並共享狀態,接口定義「can-do」能力契約支援多實現。現代 Java 通過 default/private/sealed/record 等特性,極大豐富了介面表達力,模糊了抽象類與介面邊界。遵循 LSP/ISP/DIP、組合優於繼承、優先介面編程,善用 @Override/@FunctionalInterface/sealed 編譯器輔助,即可設計出高內聚、低耦合、可演進的領域模型。

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