应优先用接口表达“能做什么”,用抽象类表达“是什么”;需共享状态或构造逻辑时选抽象类,需多行为组合或契约约束时选接口;jdk8+中default方法不改变接口本质。

选抽象类还是接口,关键看你想表达“它是什么”,还是“它能做什么”。前者用抽象类,后者用接口。
看是否需要共享状态或构造逻辑
如果多个子类要共用字段(比如 name、id)、需要统一初始化流程,或者有通用的具体方法(比如 saveLog()、validate()),那就该用抽象类。它允许定义构造方法、普通成员变量和非抽象方法。
- 抽象类可以有 protected String name;,子类直接继承使用
- 抽象类可提供 public void sleep() { System.out.println(name + " is sleeping"); }
- 接口无法保存状态,所有字段自动是 public static final,只能是常量
看是否需要多行为组合
一个类往往不止有一种能力——比如“能飞”“能跑”“能充电”。Java 不支持多继承,但允许一个类实现多个接口。这时接口就是唯一选择。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- class Drone implements Flyable, Runnable, Chargeable —— 合理且常见
- 若强行用抽象类模拟,就得把所有行为塞进一个父类,违反单一职责,也堵死其他继承路径
- 接口之间还能继承:interface SmartDevice extends Chargeable, Networked
看设计意图是模板复用还是契约约束
抽象类偏向“模板”:你继承我,就默认获得我的骨架和部分血肉;接口偏向“合同”:你签了我,就必须履行几个明确义务,至于怎么干,全由你定。
- 数据库操作模块常用抽象类封装 getConnection()、close() 等公共逻辑,子类只专注 buildQuery()
- 支付系统用接口定义 pay()、refund(),让微信支付、支付宝、银行卡各自实现,互不干扰
- 当不同领域对象(人、机器人、无人机)都需要“移动”,用 Movable 接口比硬拉一个共同父类更自然
注意 JDK8+ 的模糊地带
接口支持 default 和 static 方法后,也能提供简单实现,但这不改变它的本质——它仍是行为契约,不是状态容器。别为了少写几行代码就把本该是接口的规范改成抽象类。
- 接口里的 default void stop() { System.out.println("stopping"); } 是兜底行为,不是核心状态管理
- 抽象类中的 private void initCache() 或 protected List
history; 仍无可替代 - 如果发现抽象类里全是抽象方法,没有字段也没有具体逻辑,那它大概率该重构成接口
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










