抽象类与接口的核心区别在于设计意图:抽象类体现is-a关系,用于共享状态和逻辑骨架;接口体现can-do关系,用于定义跨类族的行为契约。

选抽象类还是接口,关键看你想解决什么问题。不是语法能写什么,而是设计想表达什么。
一、看“关系本质”:is-a 还是 can-do
抽象类回答“它是什么”,强调继承关系和身份归属。比如 Animal 抽象类定义了所有动物共有的生命状态(name、age)、基础行为(sleep())和必须实现的核心逻辑(makeSound()),Dog 和 Cat 是它的具体子类——这是典型的 is-a 关系。
接口回答“它能做什么”,不关心身份,只约定能力。比如 Flyable 接口只声明 fly() 方法,Bird、Drone、Superman 都可实现它,哪怕它们毫无继承关联——这是纯粹的 can-do 关系。
如果多个类天然属于同一类事物,并共享状态或逻辑骨架,优先考虑抽象类;如果只是临时需要某种能力,且该能力可能跨完全不同领域,就用接口。
二、看“复用需求”:要共享代码,还是要隔离实现
抽象类天然支持代码复用:它可以有构造器初始化共性字段,有 protected 方法供子类调用,有普通方法提供默认行为。例如 Shape 抽象类里封装了 color 字段和 showColor() 方法,Circle 和 Rectangle 直接继承就能用。
接口在 JDK 8 后虽支持 default 方法,但其设计初衷不是复用逻辑,而是向后兼容与能力扩展。default 方法不能访问实现类的私有状态,也不能被重载(只能被重写),本质上仍是契约的一部分,而非可复用的业务逻辑。
当你需要子类共享字段、初始化流程或可被继承的通用逻辑时,抽象类更合适;若只是为避免每个实现类都写一遍相同的行为(如日志、校验),且该行为不依赖实例状态,default 方法可以辅助,但不应替代抽象类的复用职责。
三、看“扩展约束”:单继承瓶颈 vs 多能力组合
Java 类只能单继承,所以一个类只能 extends 一个抽象类。这既是限制也是保障——它强制你明确核心父类身份,避免继承链混乱。
而一个类可以 implements 多个接口,比如 Car 可同时实现 Vehicle、Lockable、GPSNavigable,灵活叠加不同维度的能力。
当模型需要横向组合多种独立职责(如安全、监控、序列化、事件响应),接口是唯一可行路径;若已有明确的主继承线(如 Spring 中的 AbstractController),再通过接口补充额外契约,就是经典分层设计。
注意:不要为了“多继承”而强行把本该是 is-a 的关系塞进接口——比如把 “Employee 是 Person” 写成 Employee implements Person,语义错位会损害可维护性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











