抽象類VS接口:核心區(qū)別與實(shí)戰(zhàn)選擇
抽象類與接口的定義
抽象類:用abstract修飾的類,可以包含抽象方法(無(wú)實(shí)現(xiàn))和具體方法(有實(shí)現(xiàn))。抽象類無(wú)法實(shí)例化,需由子類繼承并實(shí)現(xiàn)其抽象方法。
接口:用interface定義,默認(rèn)方法均為public abstract(Java 8前),可包含常量(public static final)。Java 8后支持默認(rèn)方法(default)和靜態(tài)方法(static)。
核心區(qū)別
1. 設(shè)計(jì)目的
- 抽象類:表示“是什么”(is-a關(guān)系),強(qiáng)調(diào)類的本質(zhì)(如Animal是Cat的父類)。
- 接口:表示“能做什么”(can-do關(guān)系),定義行為契約(如Flyable接口表示可飛行)。
2. 多繼承
- 抽象類:Java單繼承,子類只能繼承一個(gè)抽象類。
- 接口:類可實(shí)現(xiàn)多個(gè)接口(如class Bird implements Flyable, Singable)。
3. 成員變量
- 抽象類:可包含普通變量和常量。
- 接口:變量默認(rèn)是public static final,必須初始化。
- 方法實(shí)現(xiàn)
- 抽象類:可包含具體方法和抽象方法。
- 接口:Java 8前所有方法均為抽象方法;Java 8后支持默認(rèn)方法和靜態(tài)方法。
- 構(gòu)造器
- 抽象類:有構(gòu)造器(用于子類初始化)。
- 接口:無(wú)構(gòu)造器。
使用場(chǎng)景
抽象類的適用場(chǎng)景
- 需要定義模板方法模式(部分邏輯固定,部分由子類實(shí)現(xiàn))。
- 多個(gè)子類有共享的公共代碼或狀態(tài)(如字段、方法)。
- 需要控制子類的構(gòu)造過(guò)程(通過(guò)抽象類的構(gòu)造器)。
abstract class Logger {
protected String format; // 共享字段
public void log(String message) {
System.out.println(format + ": " + message); // 固定邏輯
}
public abstract void setFormat(); // 子類實(shí)現(xiàn)
}
接口的適用場(chǎng)景
- 定義跨類別的行為(如Comparable、Serializable)。
- 需要多繼承行為時(shí)(如一個(gè)類需同時(shí)支持Readable和Writable)。
- 定義API契約(如Spring的Repository接口)。
interface Drawable {
void draw(); // 行為契約
}
class Circle implements Drawable {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
版本演進(jìn)的影響
- Java 8:接口支持默認(rèn)方法(default),便于擴(kuò)展接口而不破壞現(xiàn)有實(shí)現(xiàn)。
- Java 9:接口支持私有方法,用于拆分默認(rèn)方法的邏輯。
interface Vehicle {
default void start() {
System.out.println("Vehicle started");
}
}
總結(jié)選擇建議
- 優(yōu)先接口:當(dāng)行為需要跨多個(gè)不相關(guān)類時(shí)(如Serializable),或需要多繼承能力。
- 選擇抽象類:當(dāng)需要共享代碼或狀態(tài),或定義類的基礎(chǔ)模板時(shí)。
- 兩者并非互斥,可結(jié)合使用(如抽象類實(shí)現(xiàn)接口的部分方法)。

浙公網(wǎng)安備 33010602011771號(hào)