抽象类适合解决“共性实现”问题,提供可复用的状态、构造逻辑和具体方法;接口适合定义“行为契约”,支持多实现与跨类族能力组合。

选抽象类还是接口,关键看你要解决的是“共性实现”还是“行为契约”。抽象类适合提供可复用的代码骨架,接口适合定义多个不相关类都能遵守的行为规范。
什么时候该用抽象类
当你有一组类共享相同的状态(字段)、构造逻辑或部分通用实现时,抽象类更自然:
- 需要定义成员变量(比如
protected String brand)或带参数的构造器 - 已有大量可复用的具体方法(如日志记录、校验模板、默认初始化流程)
- 这些类天然属于同一继承体系(如
Animal → Dog、Vehicle → Car) - 未来可能扩展为模板方法模式(
templateMethod()调用若干abstract hook())
什么时候该用接口
当你关注“能做什么”,而非“是什么”,且希望解耦、灵活组合时,优先选接口:
- 定义跨领域行为,比如
Runnable、Comparable、Serializable - 一个类需同时具备多种角色(如
Car implements Movable, Insurable, Taxable) - 不希望强制继承关系,避免单继承限制
- 需要默认行为但又不想侵入类层次(Java 8+ 的
default方法很适合补救)
设计上容易踩的坑
混淆本质会导致后期重构成本高:
立即学习“Java免费学习笔记(深入)”;
- 为图省事在接口里塞一堆
default方法,结果接口越来越像抽象类——说明它本该是抽象类 - 用抽象类强行统一无关类(比如让
Button和DatabaseConnection继承同一个“基础类”)——违背语义一致性 - 接口中定义大量常量(
public static final int MAX_RETRY = 3)——应移至工具类或配置类,接口只管行为 - 抽象类里全是抽象方法,没任何字段或实现——那它本质上就是个接口,应改用
interface
现代 Java 的协同用法
两者不是非此即彼,而是互补:
- 接口定义能力(
Drawable、Resizable),抽象类提供基线实现(AbstractShape含color字段和drawBorder()) - 接口用
default提供向后兼容的新增方法;抽象类用protected方法供子类定制细节 - 框架设计常见模式:面向接口编程(依赖
Service),面向抽象类扩展(继承AbstractService定制逻辑)


















