抽象类表达“是什么”,体现is-a关系并支持状态与构造逻辑;接口定义“能做什么”,体现has-a能力且仅约定行为契约,支持多实现。

本质区别不在语法细节,而在设计意图和使用场景。
抽象类表达“是什么”,接口定义“能做什么”
抽象类体现的是is-a关系:Dog is a Animal,Car is a Vehicle。它描述一类事物的共性本质,天然带有继承层级和状态(比如name、id等实例变量),也适合封装可复用的逻辑(如通用的日志、校验、模板流程)。
接口体现的是has-a能力或契约:一个类has Serializable ability,has Comparable behavior,甚至has Payment capability。它不关心你是谁,只约定你能提供什么行为,因此跨类型、跨继承体系也能统一使用(比如String和Date都能实现Comparable)。
抽象类支持状态与构造逻辑,接口只能定义常量与行为
抽象类可以:
立即学习“Java免费学习笔记(深入)”;
- 声明
protected String token、private int retryCount等带访问控制的成员变量 - 定义构造器,供子类
super(...)调用,完成初始化(比如设置默认超时、加载配置) - 包含
final方法、static工具方法、甚至private辅助方法
接口只能:
- 声明
public static final字段(即常量),不能有实例状态 - 没有构造器,无法参与对象创建流程
- 方法默认
public,不能用private或protected修饰(Java 9+ 支持private默认方法,但仅限于辅助其他默认方法)
继承机制不同,决定了它们在架构中的角色
一个类只能extends一个抽象类——这是单继承限制,意味着它必须选准唯一的“父型”。这适合构建垂直业务基线,比如所有报表导出器都继承AbstractReportExporter,共享数据读取、文件压缩、异常包装等逻辑。
一个类却可以implements多个接口——这是多实现自由,意味着它可以同时具备多种正交能力。比如一个支付服务类既实现Payable,又实现Refundable,还实现Loggable,彼此无关、互不干扰。
Java 8+ 的默认方法没改变本质,只是补全了接口的实用性
接口加入default方法,是为了在不破坏已有实现的前提下扩展API(如Collection新增stream())。但它仍不能持有状态、不能调用构造器、不能替代抽象类的模板骨架作用。
真正需要共享代码+共享状态+强制初始化顺序时,抽象类不可替代;只需统一行为契约、支持灵活组合、解耦实现细节时,接口更合适。


















