抽象类回答“是什么”,体现继承关系,如animal及其子类共享本质特征;接口回答“能做什么”,体现能力契约,如flyable、swimmable支持不相关类的功能组合。

设计意图:一个讲“是什么”,一个讲“能做什么”
抽象类表达的是继承关系,回答“这个类是什么”。比如 Animal 是一个抽象类,Dog 和 Cat 都是它的子类——它们“是”动物,共享名字、呼吸、生命周期等本质特征。抽象类适合提取同一类事物的共性,包括状态(字段)和行为(方法实现)。
接口表达的是能力契约,回答“这个类能做什么”。比如 Flyable、Swimmable、Playable,一个类可以同时是鸟(Bird extends Animal implements Flyable, Swimmable),它不一定要“是”飞行器,但它“能飞”“能游”。接口关注功能组合,与类的血缘无关。
语法差异:从成员构成到使用方式
这些区别直接影响你写代码时的选择:
-
方法:抽象类可含抽象方法 + 具体方法 + 构造方法;接口在 Java 8+ 支持默认方法、静态方法、私有方法,但普通方法仍默认为
public abstract,不能有protected或private实例方法。 -
字段:抽象类的字段可任意修饰(
private、protected、public、static、final等);接口中所有字段自动是public static final,即只能是常量,且必须显式初始化。 - 构造器:抽象类可以有构造方法(用于子类初始化时调用),接口完全不允许定义构造器。
-
继承限制:一个类只能
extends一个抽象类,但可以implements多个接口——这是 Java 绕过单继承局限的关键机制。
怎么选:看你要解决的问题类型
不需要纠结“哪个更高级”,而是问自己三个问题:
- 是否需要共享代码逻辑(比如通用的日志、校验、模板流程)?→ 优先考虑抽象类。
- 是否想让不相关的类具备相同能力(比如
Button、Video、Notification都支持“点击反馈”)?→ 用接口。 - 是否要约束多个维度的行为(如既可撤销
Undoable,又可序列化Serializable,还可导出Exportable)?→ 接口天然支持这种正交扩展。
一个典型混合用法
实际项目中两者常配合使用:用抽象类搭建领域模型骨架(如 AbstractOrderService 提供统一订单创建、校验、幂等逻辑),再用接口声明横切能力(如 AsyncExecutable、Traceable、Retryable)。这样既复用核心逻辑,又保持行为解耦。
不复杂但容易忽略。









