四重奏免安装绿色版
495M · 2025-10-07
接口与抽象,Java中绕不开的主题,但是又总感觉二者之间有些东西模模糊糊没有理清,今天来认真整理一下。
纯行为契约,定义方法的签名(不包含实现)。Java 8+支持默认方法(default
)和静态方法。
Comparable
)可包含部分实现的模板,允许定义抽象方法(无实现)、具体方法、成员变量和构造器。
特性 | 接口 | 抽象类 |
---|---|---|
实例字段 | (Java 17仅支持常量) | |
构造方法 | ||
方法实现 | Java 8+支持默认/静态方法 | |
多重继承 | (多个接口) | (单继承) |
设计目的 | "能做什么"(行为) | "是什么"(层次结构) |
// 接口定义支付行为
interface PaymentProcessor {
// 抽象方法
void processPayment(double amount);
// Java 8 默认方法(可选实现)
default void validatePayment(double amount) {
if (amount <= 0) throw new IllegalArgumentException("无效金额");
}
}
// 具体实现类
class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
validatePayment(amount); // 调用默认方法
System.out.println("信用卡支付: " + amount);
}
}
// 抽象类提供模板方法
abstract class AbstractDatabaseClient {
// 共享状态
private final String connectionUrl;
// 构造器注入
public AbstractDatabaseClient(String url) {
this.connectionUrl = url;
initializeConnection();
}
// 具体方法(复用)
private void initializeConnection() {
System.out.println("初始化DB连接: " + connectionUrl);
}
// 抽象方法(子类必须实现)
public abstract void executeQuery(String sql);
}
// 具体子类
class MySQLClient extends AbstractDatabaseClient {
// 通过构造方法注入参数
public MySQLClient(String url) { super(url); }
@Override
public void executeQuery(String sql) {
System.out.println("执行MySQL查询: " + sql);
}
}
default
/static
方法private
方法(代码复用)sealed
接口/抽象类控制继承// Java 17 sealed接口示例
public sealed interface PaymentProcessor
permits CreditCardProcessor, CryptoProcessor { ... }
// 细粒度接口设计(避免God Interface)
interface Loggable { void log(); }
interface Cacheable { void cache(); }
abstract class TemplateService {
// 固定算法骨架
public final void execute() {
preProcess();
doBusinessLogic(); // 抽象钩子
postProcess();
}
protected abstract void doBusinessLogic();
}
flowchart TD
A[需要多继承?] -- Yes --> B(选接口)
A -- No --> C{需要共享状态或公共实现?}
C -- Yes --> D(选抽象类)
C -- No --> E{需要定义行为契约?}
E -- Yes --> B
E -- No --> F(可能不需要接口/抽象类)
问题:多个接口的同名默认方法引发冲突
interface A { default void foo() {} }
interface B { default void foo() {} }
class C implements A, B {} // 编译错误!
解决:在实现类中强制重写:
class C implements A, B {
@Override
public void foo() {
A.super.foo(); // 显式选择实现
}
}
问题:子类忘记调用超类构造器导致状态未初始化
abstract class AbstractResource {
private String resourceId;
protected AbstractResource(String id) { this.resourceId = id; }
}
class SubResource extends AbstractResource {
// 未调用super(id) -> NullPointerException!
}
解决:
@RequiredArgsConstructor
(Lombok)问题:向接口添加新方法导致遗留实现类报错
规避:
default
方法(向后兼容)V2
(如PaymentProcessorV2
)问题:子类错误修改抽象类共享状态:
abstract class AbstractSession {
protected List<String> sessions = new ArrayList<>();
}
class UserSession extends AbstractSession {
public void clear() { sessions.clear(); } // 影响所有子类实例!
}
规避:
private
+ 提供受保护访问器黄金法则:
sealed
限制继承(安全控制)