关键看解决“共性复用”还是“行为契约”:需共享状态、字段、构造逻辑或部分实现时选抽象类;需跨类型统一能力、多实现或对接框架生态时选接口;二者可组合使用。

选抽象类还是接口,关键看你要解决的是“共性复用”问题,还是“行为契约”问题。
需要共享状态和部分实现时,用抽象类
当多个子类有共同字段(比如 name、id、createTime),或已有通用逻辑(比如日志记录、参数校验、模板方法骨架),抽象类能直接承载这些内容。
- 可以定义 protected 成员变量,子类继承后直接访问
- 可提供 带实现的普通方法,避免重复编码
- 支持 构造器,方便子类初始化时统一处理(如校验非空、设置默认值)
- 适合纵向继承体系,比如 PaymentAbstract 作为支付基类,子类 AlipayPayment 和 WechatPayment 复用签名生成、异步回调解析等逻辑
需要定义能力契约或跨类型协作时,用接口
当不同类之间没有继承关系,但需统一暴露某种能力(比如可比较、可序列化、可重试、可熔断),接口是更自然的选择。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 一个类可 同时实现多个接口,例如 User implements Comparable
, Serializable, Cloneable - 接口方法默认 public,天然面向调用方,利于解耦
- Java 8+ 的 default 方法允许在不破坏现有实现的前提下扩展行为(如给所有 Repository 接口新增 countByStatus())
- 适合横向能力抽象,比如 Retryable、AsyncExecutable、Exportable,任何业务类按需实现即可
有继承约束但又需扩展行为,两者可组合使用
抽象类本身可以 implements 接口,把“是什么”和“能做什么”分层表达。
- 例如:抽象类 BaseService 实现了 InitializingBean 和 DisposableBean,子类自动获得初始化/销毁生命周期管理
- 再比如:抽象类 ReportGenerator 实现 Runnable,让所有报表生成器天然支持线程调度
- 这样既保留了继承结构的复用优势,又通过接口接入标准生态
未来可能被多继承或框架集成时,优先接口
Spring、Dubbo、MyBatis 等主流框架大量依赖接口做代理、注入和扩展。用接口定义服务契约,更容易对接 AOP、RPC、泛型工具等基础设施。
- Service 层推荐接口 + 实现类分离:如 UserService(接口) + UserServiceImpl(具体实现),便于单元测试 Mock 和动态代理
- DTO、VO、Query 对象虽无行为,但若需统一标记语义(如 Validatable、Versioned),也建议用空接口而非抽象类
- 避免为“为了抽象而抽象”引入抽象类——如果只有抽象方法、无字段、无构造逻辑、无复用实现,那它本质上就是个接口
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










