判断是否该用继承,关键看两个类之间是否为“是一个”(is-a)关系:dog是animal、manager是employee属合理继承;car是engine、student是filelogger则错误,应改用组合。

判断是否该用继承,关键看两个类之间是不是“是一个”(is-a)关系,而不是“有一个”(has-a)或“用一用”(uses-a)关系。如果只是想复用代码,大概率不该用继承——组合更安全、更灵活。
看是否满足“is-a”语义
这是最核心的判断标准。子类必须在逻辑上天然属于父类的一种具体类型:
- ✅ 合理:
Dog extends Animal—— 狗是一种动物 - ✅ 合理:
Manager extends Employee—— 经理是一种员工 - ❌ 不合理:
Car extends Engine—— 汽车不是一种发动机(而是“有”一个发动机) - ❌ 不合理:
Student extends FileLogger—— 学生不是一种日志器(只是可能用它记录信息)
检查父类是否稳定且可被合理抽象
继承会把子类和父类强耦合。如果父类还在频繁修改行为、字段或接口,子类很容易被牵连出错:
- 父类是抽象类或接口,只定义契约(如
abstract void fly()),不包含易变的具体实现,更适合继承 - 父类是工具类或工具方法集合(如
DateUtils、StringUtils),不适合被继承——它们没有“类型身份”,只是功能集合 - 父类若大量使用
private字段+public方法封装内部逻辑,子类很难安全扩展,这时应考虑组合
评估是否真正需要多态和统一类型处理
如果项目中根本不需要把不同子类对象当作同一父类类型来统一操作,那继承就失去了主要价值:
- 需要写类似
void process(List<animal> animals)</animal>这样的通用方法?→ 继承有意义 - 所有子类都各自独立使用,从不共用参数类型、不参与同一批策略调度?→ 很可能只是复制粘贴式复用,该用组合或提取工具方法
- 子类重写方法后,调用方仍能无感知地运行(里氏替换原则)?如果重写后行为差异大到破坏原有逻辑,说明继承关系设计错了
警惕“为复用而继承”的陷阱
很多初学者把继承当成“抄代码快捷键”。但 Java 的继承是语义绑定 + 行为继承 + 类型兼容三位一体,不是单纯的代码搬运工:
- 想复用几个静态工具方法?→ 直接调用,别继承
- 想共享一组配置或状态?→ 用组合(
private Config config)更清晰可控 - 子类只为了重写全部方法、屏蔽父类大部分逻辑?→ 这已经违背了“is-a”,该重构为策略模式或委托
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











