抽象类回答“它是什么”,强调is-a关系和代码复用;接口回答“它能做什么”,强调can-do契约和多能力组合。

直接说核心:抽象类回答“它是什么”,接口回答“它能做什么”。这不是语法口诀,而是设计时的第一判断依据。
看建模意图:is-a 还是 can-do
如果几个类天然属于同一类事物,比如 猫、狗、鸟 都是 动物,那用抽象类——强调“是”的归属关系。父类可封装共用字段(如 name、age)、构造逻辑、通用行为(如 breathe()),子类只需补全差异部分(如 makeSound())。
如果不同类之间没有继承关系,但需要统一对外提供某种能力,比如 无人机、小鸟、超人 都能飞,那就抽成接口 Flyable——不关心它们是谁,只约定“能飞”这个契约。一个类可以同时实现 Flyable、Swimmable、Chargeable,这是接口的天然优势。
看代码职责:复用逻辑 还是 定义规范
抽象类的核心价值是减少重复代码。它允许你写 80% 的流程(比如支付中的签名校验 + 流水生成 + 日志记录),只留 20% 由子类决定(比如调用微信还是支付宝网关)。这种“模板方法模式”依赖抽象类的构造器、成员变量和具体方法。
接口的核心价值是解耦与协作。它让前端只依赖 PaymentService 接口,后端可随意替换为 AlipayImpl、WechatImpl 或 MockImpl,只要符合接口定义,系统就无需改动。这种灵活性来自接口的无状态、无构造、纯行为契约特性。
看语言能力:能存状态吗?能有多个爹吗?
这些语法差异背后都有明确的设计取舍:
- 抽象类可以有 构造方法 和 普通成员变量 —— 因为它要初始化子类共享的状态;
- 接口不能有构造器,所有字段自动是 public static final —— 因为它不承载实例状态,只声明能力边界;
- 一个类只能 extends 一个抽象类,但可以 implements 多个接口 —— 单继承保证类体系清晰,多实现支持能力组合;
- Java 8+ 后接口支持 default 和 static 方法,但它们不能访问实例状态 —— 这恰恰印证了接口的定位:提供工具性默认行为,而非对象生命周期管理。
看实际选型:三句话快速决策
遇到抽象需求时,问自己三个问题:
- 这些类有没有共同的属性或初始化逻辑?→ 有,优先考虑抽象类;
- 是否需要让不相关的类(比如 Order、User、Report)都具备某项能力?→ 是,必须用接口;
- 未来是否可能让一个类同时拥有多种独立能力(如可打印、可导出、可审计)?→ 是,接口是唯一选择。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











