Java中有兩個非常重要的概念——抽象類和接口。它們都能幫助我們設計更靈活、更清晰的代碼結構,但很多初學者容易把它們混淆,甚至不知道什麼時候該用哪個。今天我們就來詳細聊聊它們的區別,以及各自適用的場景。
1. 定義方式不同¶
抽象類和接口的聲明方式有明顯區別:
- 抽象類:使用 abstract class 聲明,例如:
abstract class Animal { // 抽象類
// 可以有抽象方法和具體方法
public abstract void makeSound(); // 抽象方法(無方法體)
public void breathe() { // 具體方法(有方法體)
System.out.println("動物在呼吸");
}
}
- 接口:使用
interface聲明,例如:
interface Flyable { // 接口
void fly(); // 默認是 public abstract(JDK8前)
}
2. 繼承/實現關係不同¶
- 抽象類:類通過
extends繼承抽象類(Java是單繼承,一個類只能繼承一個抽象類)。 - 接口:類通過
implements實現接口(一個類可以實現多個接口,實現多繼承的效果);接口之間也可以通過extends多繼承。
3. 方法和成員變量的區別¶
方法¶
- 抽象類:可以包含抽象方法(
abstract,無方法體)和具體方法(有方法體)。如果類包含抽象方法,自身必須是抽象類。 - 接口:JDK8之前,所有方法默認是
public abstract(必須實現);JDK8+新增了默認方法(default,有方法體)和靜態方法(static,有方法體),例如:
interface Printable {
default void print() { // 默認方法,所有實現類可直接使用
System.out.println("默認打印行爲");
}
static void staticMethod() { // 靜態方法,有方法體
System.out.println("靜態方法");
}
}
成員變量¶
- 抽象類:可以有各種修飾符的成員變量(實例變量、類變量),例如:
abstract class Animal {
private String name; // 實例變量
public static int count = 0; // 類變量(靜態變量)
}
- 接口:只能有
public static final的成員變量(即常量,不能修改),例如:
interface Constants {
int MAX_SIZE = 100; // 常量(默認public static final)
}
4. 構造方法¶
- 抽象類:可以有構造方法,用於子類初始化時調用(抽象類本身不能實例化,但子類通過
super調用父類構造方法)。 - 接口:沒有構造方法(因爲接口不能被實例化,也無需初始化)。
5. 設計目的不同¶
抽象類:強調“是什麼”(繼承關係)¶
抽象類更像一個“模板”,用於描述“這一類事物的共同特徵”。例如:
- 定義 Animal 抽象類,包含“呼吸”(breathe())的具體方法(所有動物都會呼吸),以及“發出聲音”(abstract makeSound())的抽象方法(具體動物聲音不同,由子類實現)。
- 子類(如 Dog、Cat)繼承 Animal 後,直接複用 breathe() 方法,只需實現 makeSound()。
接口:強調“能做什麼”(實現關係)¶
接口更像一個“能力列表”,用於描述“某類事物能完成的行爲”。例如:
- 定義 Flyable 接口,僅規定“能飛”(fly())的方法,不關心“誰在飛”。
- 不同類(如 Bird、Airplane)都能實現 Flyable 接口,各自實現 fly() 方法(鳥扇翅膀飛,飛機靠引擎飛)。
什麼時候用抽象類?¶
- 需要共享代碼:抽象類可以提供通用方法和變量,子類繼承後直接複用,避免重複代碼。例如:
Animal抽象類中的breathe()方法。 - 強“是一種”關係:子類和父類是“是一種”(
is-a)關係。例如:Cat是Animal的子類,用抽象類更合適。 - 部分實現+部分抽象:抽象類可以包含具體方法,子類只需實現抽象方法。例如:
Shape抽象類有計算面積的具體方法,子類Circle只需實現getRadius()(半徑已知)。
什麼時候用接口?¶
- 多實現場景:一個類需要實現多個獨立行爲(Java類只能單繼承,但可多實現接口)。例如:
Duck類可以同時實現Flyable和Swimmable接口。 - 定義行爲規範:接口僅規定“做什麼”,不關心“怎麼做”。例如:定義
Printable接口,任何類實現後都必須有print()方法(具體實現由類自己決定)。 - 無繼承關係的共同行爲:不同類之間無“是一種”關係,但有共同行爲。例如:
Bird和Airplane都能飛,可共同實現Flyable接口。
總結¶
- 抽象類:是“模板”,提供部分實現,用於有繼承關係的類共享代碼,強調“是什麼”。
- 接口:是“契約”,僅規定規則,用於多實現場景或定義行爲規範,強調“能做什麼”。
如果不確定用哪個,記住:需要繼承共享代碼時選抽象類,需要多實現或行爲規範時選接口。