应根据关系类型、代码复用需求和继承限制选择:是“是什么”用抽象类,“能做什么”用接口;需共享状态或构造逻辑选抽象类,需多继承或正交能力组合选接口;api设计中常协同使用,接口定契约,抽象类提供骨架。

看关系还是看能力
如果几个类之间存在明显的“是什么”关系,比如“狗是动物”“猫是动物”,那抽象类更合适。它能自然表达这种层级继承,并共享字段、构造逻辑和通用方法。
如果关注的是“能做什么”,比如“鸟能飞”“飞机也能飞”,但二者毫无继承关系,那就该用接口。接口不关心你是谁,只约定你能提供什么行为。
看能不能复用代码
需要子类共用状态或逻辑时,抽象类是首选:
- 有成员变量(如protected String id、private final Config config)
- 需要构造器做初始化(如校验必填参数、建立连接池)
- 有模板方法(比如execute()封装签名→调用→解析全流程,只留buildRequest()由子类实现)
接口无法持有状态,也不能定义构造器,它的 default 方法只适合无状态的轻量逻辑(比如空值检查、简单转换),复杂流程仍得靠抽象类。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
看需不需要多继承
Java 不允许类多重继承,但允许一个类实现多个接口。所以当需要叠加多种正交能力时,接口是唯一选择:
- class OrderService extends AbstractService implements AsyncCapable, Retryable, Tracable
- 每个接口代表一个独立维度:异步、重试、链路追踪——可自由组合,互不影响
若强行用抽象类来承载这些能力,就会陷入单继承瓶颈,还容易让父类职责膨胀、难以维护。
API 或 SDK 设计中的典型组合
工业级设计往往不是二选一,而是协同使用:
- 对外暴露稳定契约:用接口(如PaymentClient),方便 Mock、替换实现、平滑升级
- 对内提供接入骨架:用抽象类(如AbstractHttpClient),内置 HTTP 客户端、签名工具、日志模板等复用逻辑
- 实现类写法固定:class WechatPayClient extends AbstractHttpClient implements PaymentClient, RefundCapable
这样既保证了调用方简洁,又降低了集成方门槛,还保留了扩展弹性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










