Java中的接口(Interface)与抽象类(Abstract Class)

前言

接口与抽象,Java中绕不开的主题,但是又总感觉二者之间有些东西模模糊糊没有理清,今天来认真整理一下。

一、基本原理

接口

纯行为契约,定义方法的签名 (不包含实现)。Java 8+支持默认方法(default)和静态方法。

  • 实现多继承行为:类可同时实现多个接口
  • 强制统一规范 :不同类的相同行为标准化(如Comparable
  • 解耦:声明与实现分离(依赖倒置原则)

抽象类

可包含部分实现的模板,允许定义抽象方法(无实现)、具体方法、成员变量和构造器。

  • 代码复用:为继承体系提供公共实现(如模板方法模式)
  • 状态共享:可在基类中封装共享状态(字段)
  • 控制扩展:定义必须由子类实现的约束

核心差异

特性 接口 抽象类
实例字段 ❌(Java 17仅支持常量)
构造方法
方法实现 Java 8+支持默认/静态方法
多重继承 ✅(多个接口) ❌(单继承)
设计目的 "能做什么"(行为) "是什么"(层次结构)

二、普遍用法

1. 定义行为契约(接口)

java 复制代码
// 接口定义支付行为
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);
    }
}

2. 复用公共逻辑(抽象类)

java 复制代码
// 抽象类提供模板方法
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);
    }
}

⚠️ 版本差异说明

  • Java 8+ :接口支持default/static方法
  • Java 9+ :接口支持private方法(代码复用)
  • Java 17+sealed接口/抽象类控制继承
java 复制代码
// Java 17 sealed接口示例
public sealed interface PaymentProcessor 
    permits CreditCardProcessor, CryptoProcessor { ... }

三、设计原则

优先选择接口(符合ISP原则)

java 复制代码
// 细粒度接口设计(避免God Interface)
interface Loggable { void log(); }
interface Cacheable { void cache(); }

抽象类用于模板方法

java 复制代码
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(可能不需要接口/抽象类)

四、避坑

⚠️ 坑1:接口默认方法冲突

问题:多个接口的同名默认方法引发冲突

java 复制代码
interface A { default void foo() {} }
interface B { default void foo() {} }
class C implements A, B {} // 编译错误!

解决:在实现类中强制重写:

java 复制代码
class C implements A, B {
    @Override 
    public void foo() {
        A.super.foo(); // 显式选择实现
    }
}

⚠️ 坑2:抽象类构造器陷阱

问题:子类忘记调用超类构造器导致状态未初始化

java 复制代码
abstract class AbstractResource {
    private String resourceId;
    protected AbstractResource(String id) { this.resourceId = id; }
}
class SubResource extends AbstractResource {
    // 未调用super(id) -> NullPointerException!
}

解决

  1. IDE配置@RequiredArgsConstructor(Lombok)
  2. 代码审查强制验证

⚠️ 坑3:扩展性破坏

问题:向接口添加新方法导致遗留实现类报错

规避

  • Java 8+:优先用default方法(向后兼容)
  • 发布新接口V2(如PaymentProcessorV2

⚠️ 坑4:状态泄漏(抽象类特有)

问题:子类错误修改抽象类共享状态:

java 复制代码
abstract class AbstractSession {
    protected List<String> sessions = new ArrayList<>();
}
class UserSession extends AbstractSession {
    public void clear() { sessions.clear(); } // 影响所有子类实例!
}

规避

  1. 字段设为private + 提供受保护访问器
  2. 文档明确状态所有权

结语

黄金法则

  1. 行为定义必选接口(特别是公共API)
  2. 纵向复用代码选抽象类(如领域模型基类)
  3. Java 17+优先使用sealed限制继承(安全控制)
相关推荐
Terio_my4 小时前
Java bean 数据校验
java·开发语言·python
Tony Bai4 小时前
【Go开发者的数据库设计之道】07 诊断篇:SQL 性能诊断与问题排查
开发语言·数据库·后端·sql·golang
超级大只老咪4 小时前
何为“类”?(Java基础语法)
java·开发语言·前端
花花鱼5 小时前
spring boot项目使用tomcat发布,也可以使用Undertow(理论)
spring boot·后端·tomcat
我笑了OvO5 小时前
C++类和对象(1)
java·开发语言·c++·类和对象
weixin_436525076 小时前
Gitee - IDEA 主支 master 和分支 dev 的使用
java·ide·intellij-idea
你的人类朋友6 小时前
快速搭建redis环境并使用redis客户端进行连接测试
前端·redis·后端
sheji34167 小时前
【开题答辩全过程】以 YF精品视频动漫平台为例,包含答辩的问题和答案
java·eclipse
小蕾Java7 小时前
Java 开发工具,最新2025 IDEA 使用
java·ide·intellij-idea
是席木木啊7 小时前
Idea升级到2024版本:“marketplace plugins are not loaded”解决方案
java·ide·intellij-idea