在面向對象領域,**抽象類** 表示一種「不完整」的概念——它定義了**共同協議**(抽象方法)與**共享實作**(具體方法/欄位),但自身無法實例化。就像「動物」這個概念:你知道它會叫、會動,但無法具體描述長什麼樣;必須由「貓」「狗」等具體子類補全細節。抽象類是**多態**與**模板方法模式**的核心載體,強制子類遵循統一介面,同時允許差異化實現。
| 規則 | 說明 | 代碼示例 |
|---|---|---|
| 不能實例化 | new Animal() 編譯錯誤,只能 Animal a = new Cat() | 編譯器強制檢查 |
| 含 abstract 方法 → 類必須 abstract | 單個抽象方法就要求類聲明 abstract | abstract class A { abstract void m(); } |
| abstract 方法無方法體 | 以分號結尾,子類**必須**重寫(除非子類也是 abstract) | abstract void cry(); |
| 可包含具體方法/欄位/構造器 | 共享邏輯、狀態初始化,子類可直接繼承或覆蓋 | public void breathe() { ... } |
| abstract 不能與 final 並列修飾類 | final 禁止繼承,abstract 強制繼承,語義衝突 | ❌ abstract final class A {} |
| abstract 方法不能為 private/static/final/native | 需被子類覆蓋,故必須可見、非靜態、非最終、非原生 | ❌ abstract private void m(); |
| 子類抽象方法不可與父類同名 | 避免遮蔽混淆,編譯器報錯 | ❌ 子類再宣告 abstract void cry(); |
| 維度 | 抽象類 | 介面 |
|---|---|---|
| 關係語義 | is-a(強關係,單繼承) | can-do / has-capability(弱關係,多實現) |
| 狀態 | 可有實例欄位(狀態) | 僅常量 static final,Java 8+ 可有 default/static 方法 |
| 構造器 | 有,供子類 super() 調用 | 無 |
| 訪問修飾 | 任意(private/protected/public) | 隱含 public,Java 9+ 可 private 方法 |
| 演進成本 | 新增方法不破壞子類 | Java 8 前新增方法破壞實現類,default 方法緩解 |
**原則**:「預設用介面,需要共享代碼/狀態時用抽象類」。Java 8 後介面引入 default 方法,邊界模糊化,但抽象類仍是**單繼承層次結構**的唯一選擇。
抽象類定義演算法骨架,將易變步驟延遲到子類實現:
abstract class DataProcessor {
// 模板方法:final 禁止覆蓋,鎖定流程
public final void process() {
readData();
String raw = parseData();
String result = transform(raw); // 抽象步驟
writeData(result);
cleanup();
}
// 鉤子方法:預設實現,子類可選擇性覆蓋
protected void cleanup() { System.out.println("默認清理"); }
// 抽象方法:強制子類實現
protected abstract String transform(String raw);
// 具體方法:共享邏輯
private void readData() { /* ... */ }
private String parseData() { return "raw"; }
private void writeData(String d) { /* ... */ }
}
// 具體實現
class JsonProcessor extends DataProcessor {
@Override protected String transform(String raw) {
return "JSON:" + raw.toUpperCase();
}
@Override protected void cleanup() {
super.cleanup(); // 可選調用父類邏輯
System.out.println("JSON 專用清理");
}
}
**優勢**:流程集中控制、避免代碼重複、反轉控制(父類調用子類實現)。廣泛應用於框架設計(Servlet service()、JUnit runTest()、Spring JdbcTemplate)。
// 抽象基類
public abstract class Animal {
protected String name; // 共享欄位
public Animal(String name) { this.name = name; } // 構造器供子類調用
// 抽象方法:強制實現
public abstract void cry();
// 具體方法:共享行為
public void sleep() { System.out.println(name + " 正在睡覺..."); }
// final 方法:禁止覆蓋,核心邏輯保護
public final String getName() { return name; }
}
// 具體子類
public class Cat extends Animal {
public Cat(String name) { super(name); }
@Override public void cry() { System.out.println(name + ":喵喵~"); }
}
public class Dog extends Animal {
public Dog(String name) { super(name); }
@Override public void cry() { System.out.println(name + ":汪汪!"); }
}
// 測試多態
public class Zoo {
public static void main(String[] args) {
List<Animal> animals = Arrays.asList(new Cat("小花"), new Dog("大黃"));
animals.forEach(a -> {
System.out.print(a.getName() + " ");
a.cry(); // 動態綁定,調用具體實現
a.sleep();
});
}
}
final class Utils { private Utils() {} }super(...),否則編譯錯誤public,符合介面隔離原則抽象類是 Java 面向對象設計的**基石**:它以「不完整」換取「擴展點」,以「單繼承」換取「狀態共享」。掌握其語法約束、理解與介面的本質差異、熟練運用模板方法模式,是寫出高內聚、低耦合、易擴展代碼的關鍵。記住:**為介面編程,用抽象類共享實現**,讓設計既靈活又穩健。