抽象類是「具體類」與「接口」之間的中間層:既能像接口定義契約(抽象方法),又能像具體類提供共享實現(普通方法/字段/構造器)。本文從語法規則、記憶體模型、模板方法模式、與接口對比、常見誤區五個維度,徹底講透抽象類精髓。
| 規則 | 說明 |
|---|---|
| 關鍵字 | abstract class ClassName |
| 抽象方法 | abstract ReturnType methodName(Params); — 無方法體,子類必須實現(或繼續聲明 abstract) |
| 實例化 | 不能直接 new,只能 new 具體子類 |
| 構造器 | **有構造器**(供子類 super() 調用),但不能是 abstract |
| 字段 | 可有實例字段、靜態字段、常量 |
| 普通方法 | 可有完整實現,子類可繼承、可覆寫 |
| final 方法 | 可防止子類覆寫,鎖定演算法骨架 |
| static 方法 | 屬於類,不可覆寫(隱藏),工具方法常用 |
// 父類抽象類
abstract class Animal {
String name; // 實例字段 → 子類對象各自一份
static int count = 0; // 靜態字段 → 類級別一份
Animal(String n) { name = n; count++; } // 構造器
abstract void sound(); // 抽象方法 → 子類必須實現
void breathe() { // 普通方法 → 子類共享
System.out.println(name + " 呼吸中...");
}
}
// 子類
class Cat extends Animal {
Cat(String n) { super(n); } // 必須調用父構造器
void sound() { System.out.println("喵~"); } // 實現抽象方法
}
new Cat() → Animal() 初始化父字段 → Cat() 初始化子字段。null 槽位,子類實現後填入具體入口。abstract class DataProcessor {
// 最終算法骨架:final 防止子類破壞流程
public final void process() {
readData();
handleData();
writeResult();
}
// 鉤子方法:提供默認實現,子類可選覆寫
protected void readData() { System.out.println("默認讀取..."); }
protected void writeResult() { System.out.println("默認寫入..."); }
// 抽象方法:強制子類實現核心邏輯
protected abstract void handleData();
}
// 子類只關注核心邏輯
class CsvProcessor extends DataProcessor {
protected void handleData() { System.out.println("CSV 解析處理"); }
}
class JsonProcessor extends DataProcessor {
protected void handleData() { System.out.println("JSON 解析處理"); }
// 可選覆寫鉤子
protected void readData() { System.out.println("從 HTTP 讀取 JSON"); }
}
好萊塢原則:「別調用我們,我們會調用你」——父類控制流程,子類填充細節。
| 維度 | 抽象類 | 接口 |
|---|---|---|
| 繼承/實現 | 單繼承 extends | 多實現 implements |
| 字段 | 實例/靜態/常量 | 僅 public static final 常量 |
| 構造器 | 有(初始化共享狀態) | 無 |
| 方法實現 | 任意(抽象/普通/final/static/private) | JDK 8 前全抽象;JDK 8+ 默認/靜態/私有 |
| 訪問修飾 | 任意 | 默認 public,JDK 9+ 可 private |
| 設計意圖 | Is-a 關係、共享代碼/狀態、強制規範骨架 | Can-do 能力、多實現組合、SPI 擴展、函數式接口 |
Animal → Mammal → Cat) → 抽象類Comparable、Runnable、Repository) → 接口abstract class Base { } 合法,常用於禁止實例化的工具類基類或強制子類化。private 子類不可見無法實現;static 屬於類不屬於實例;final 禁止覆寫 — 三者與 abstract 互斥。private/final/static 方法。public static void main(String[] args),可直接運行測試共享邏輯。class C extends AbstractBase implements InterfaceA, InterfaceB。AbstractList:實現 List 介面大部分方法,子類只需實現 get(int)、size() 兩個核心方法。InputStream/OutputStream:定義 read()/write(int) 抽象方法,提供 read(byte[])、skip() 等模板方法。HttpServlet:service() 模板方法分發 doGet/doPost,子類覆寫具體 HTTP 方法。AbstractQueuedSynchronizer (AQS):同步器框架核心,模板方法控制獲取/釋放流程,子類實現 tryAcquire/tryRelease。抽象類是「半成品」的藝術:定義骨架、共享血肉、留白靈魂。善用模板方法、鉤子方法、final 骨架鎖定,能讓框架代碼既靈活又受控,是庫設計者的核心基本功。