核心是用组合、接口和明确契约替代继承:将“是不是”转为“有没有/能不能”,dog 持有 nameholder 和 soundemitter;用小接口(如 readable)按需实现;继承限2层,关键类/方法加 final;protected 仅用于明确定义的扩展点并配 javadoc。

避免滥用继承导致的高耦合,核心是把“是不是”关系换成“有没有”或“能不能”关系,用组合、接口和明确契约代替层层 extends。
优先用组合替代继承
把可复用的功能抽成独立类,让主类持有它,而不是让它变成子类。比如名字管理、声音行为、状态机逻辑,都可以封装成单独组件。
- Dog 类不再继承 Animal,而是持有一个 NameHolder 和一个 SoundEmitter 实例
- 新增行为只需替换或新增组件,不影响 Dog 的结构和已有逻辑
- 测试更简单:NameHolder 可单独 mock,不用构造整个继承链
用接口定义能力,而非类继承
把“能做什么”声明为接口,让类去实现,而不是靠父类强塞行为。Java 的 implements 比 extends 更灵活、更安全。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 定义 Readable、Printable、Serializable 等小接口,按需组合
- 避免大而全的 BaseService 继承体系,改用接口 + 默认方法提供基础能力
- Spring 等框架天然支持面向接口编程,AOP、注入、代理都更顺畅
控制继承深度与范围
真要用继承,必须设边界。Java 单继承本身已是一种约束,但还需主动加固。
- 继承层级不超过 2 层(如 A → B → C,不建议再加 D)
- 不打算被继承的类,直接加 final;关键方法用 final 修饰,防止意外重写
- 想开放扩展但限制实现方?用 sealed 接口(Java 15+),显式列出允许的实现类
明确 protected 的契约含义
protected 不只是“子类能访问”,更是“我公开了一个稳定扩展点”。滥用它会让父类实现细节暴露给子类。
- 只对真正需要子类定制的方法设为 protected,并在 JavaDoc 中说明用途和约束
- 避免 protected 字段,改用 protected getter/setter,保留修改余地
- 父类构造器里不要调用可重写方法,否则子类字段可能未初始化就执行
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










