在 Java 面向對象設計中,abstract class(抽象類)與 interface(接口)是支撐多態與抽象的兩大基石。雖然 Java 8 後接口引入默認方法、靜態方法、私有方法,二者語法邊界模糊,但設計意圖與適用場景本質不同。本文從語法對比、設計哲學、代碼實戰、選型決策四個維度深度剖析。
| 特性 | 抽象類 | 接口 |
|---|---|---|
| 關鍵字 | abstract class |
interface |
| 繼承/實現 | 單繼承 extends |
多實現 implements |
| 構造方法 | 有(子類調用 super()) |
無 |
| 字段類型 | 任意(實例/靜態/常量) | 隱式 public static final 常量 |
| 方法修飾符 | 任意 | 隱式 public(Java 9+ 可 private) |
| 默認方法 | 普通方法即可 | Java 8+ default |
| 靜態方法 | 支援 | Java 8+ 支援 |
| 訪問權限 | 任意 | 隱式 public |
抽象類 表達 「是一種」 關係 —— 核心領域模型的骨架,定義實體的本質屬性與共性行為。
接口 表達 「像一種」/「具備某種能力」 關係 —— 定義行為契約,支援橫向擴展與多重組合。
// 抽象類:定義「人」的本質
public abstract class Human {
protected String name;
protected int age;
public Human(String name, int age) {
this.name = name;
this.age = age;
}
// 共性行為:吃飯(具體方式由子類定義)
public abstract void eat();
// 模板方法:日常作息(定義骨架)
public final void dailyRoutine() {
wakeUp();
eat();
work();
sleep();
}
private void wakeUp() { System.out.println(name + " 起床"); }
protected abstract void work();
private void sleep() { System.out.println(name + " 睡覺"); }
}
// 接口:定義「飛行能力」契約
public interface Flyable {
void fly(); // 行為契約
default void land() { System.out.println("降落"); } // 默認實現
}
// 具體類:亞洲人(繼承本質,實現能力)
public class Asian extends Human {
public Asian(String name, int age) { super(name, age); }
@Override public void eat() { System.out.println(name + " 用筷子吃飯"); }
@Override protected void work() { System.out.println(name + " 寫代碼"); }
}
// 具體類:美國超人(繼承本質 + 實現多種能力)
public class AmericanSuperman extends Human implements Flyable, Swimmable {
public AmericanSuperman(String name, int age) { super(name, age); }
@Override public void eat() { System.out.println(name + " 用刀叉吃飯"); }
@Override protected void work() { System.out.println(name + " 拯救世界"); }
@Override public void fly() { System.out.println(name + " 在天空飛翔"); }
@Override public void swim() { System.out.println(name + " 在海裡游泳"); }
}
// 錯誤:Bird 繼承 Animal,但 Penguin 不會飛卻被迫繼承 fly()
public abstract class Bird extends Animal {
public abstract void fly(); // 強制所有鳥會飛
}
public interface Flyable { void fly(); }
public interface Swimmable { void swim(); }
public class Eagle extends Bird implements Flyable { ... }
public class Penguin extends Bird implements Swimmable { ... }
public class Duck extends Bird implements Flyable, Swimmable { ... }
public abstract class DataExporter {
// 最終方法鎖定算法骨架
public final void export() {
connect();
String data = queryData();
String formatted = format(data);
write(formatted);
close();
}
protected abstract void connect();
protected abstract String queryData();
protected abstract String format(String data);
protected abstract void write(String formatted);
protected abstract void close();
}
public interface Loggable {
void log(String msg);
// Java 8+ 默認方法,現有實現類無需修改
default void logError(String error) {
log("[ERROR] " + error);
}
}
正確選擇抽象類與接口,不僅是語法問題,更體現對業務領域的理解深度。遵循「高內聚、低耦合、接口隔離、里氏替換」原則,讓設計經得起時間考驗。