Java接口和抽象類是面向對象編程中實現抽象的兩種機制,它們在語法、設計目的和使用場景上有顯著區別:
一、核心區別
?定義方式?
- 抽象類:使用
abstract class
聲明,可包含抽象方法和具體方法45。 - 接口:使用
interface
聲明,方法默認是public abstract
(Java 8+支持默認方法和靜態方法)45。
- 抽象類:使用
?方法實現?
- 抽象類:可提供方法的具體實現,子類可選擇重寫或繼承13。
- 接口:方法默認無實現(Java 8前),實現類必須提供所有抽象方法的實現47。
?成員變量?
- 抽象類:可包含普通成員變量和靜態變量512。
- 接口:只能包含
public static final
常量412。
?構造方法?
- 抽象類:可以有構造方法(用于子類初始化)310。
- 接口:不能有構造方法57。
?繼承與實現?
- 抽象類:單繼承(一個類只能繼承一個抽象類)45。
- 接口:多實現(一個類可實現多個接口)47。
二、示例對比
1. 抽象類示例
public abstract class Animal {private String name; // 普通成員變量 public Animal(String name) { // 構造方法 this.name = name;}public abstract void makeSound();// 抽象方法public void sleep() {// 具體方法System.out.println(name + "正在睡覺");}}public class Dog extends Animal {public Dog(String name) {super(name);}@Overridepublic void makeSound() {System.out.println("汪汪!");}}
2. 接口示例
public interface Drawable {String COLOR = "black"; // 常量(默認public static final)void draw(); // 抽象方法default void resize() { // 默認方法(Java 8+)System.out.println("調整大小");}
}public class Circle implements Drawable {@Overridepublic void draw() {System.out.println("繪制圓形,顏色:" + COLOR);}
}
三、應用場景
- ?抽象類?:適合定義模板或基類,封裝子類共有的狀態和行為(如
Animal
的name
屬性和sleep
方法)13。 - ?接口?:適合定義行為契約(如
Runnable
的run()
),實現多態和解耦47。
?關鍵設計原則?:
- 需要共享代碼或狀態時用抽象類310。
- 需要定義多組不相關行為時用接口57。
Java 8對接口進行了重大增強,主要引入了以下新特性:
一、默認方法(Default Methods)
- ?定義?:使用
default
關鍵字修飾的實例方法,提供默認實現24 - ?特點?:
- 實現類可直接繼承或重寫默認方法
- 通過
接口名.super.方法名()
調用父接口的默認實現4
- ?示例?:
interface Formula {double calculate(int a);default double sqrt(int a) {return Math.sqrt(a);} }
二、靜態方法(Static Methods)
- ?定義?:使用
static
關鍵字修飾的方法,屬于接口本身14 - ?特點?:
- 只能通過接口名調用(如
接口名.方法名()
) - 不會被實現類繼承1
- 只能通過接口名調用(如
- ?示例?:
interface DataProcessor {static void printInfo() {System.out.println("DataProcessor v1.0");} }
三、函數式接口(Functional Interface)
- ?定義?:僅包含一個抽象方法的接口(可含多個默認/靜態方法)13
- ?標注?:使用
@FunctionalInterface
注解強化語義3 - ?內置類型?:
Predicate<T>
:條件判斷(test(T t)
)Function<T,R>
:數據轉換(apply(T t)
)Consumer<T>
:數據消費(accept(T t)
)3
四、方法沖突解決規則
當實現多個接口且存在同名默認方法時,必須顯式重寫該方法4:
public class C implements A, B {@Overridepublic void execute() {A.super.execute(); // 顯式選擇接口A的實現}
}
這些特性使接口既能保持行為契約的定義能力,又能提供部分實現邏輯,顯著提升了代碼復用性和擴展性