Java继承的本质是语义上的“is-a”关系,用于代码复用与扩展,需严格遵循抽象边界、控制访问权限、优先组合而非滥用继承,并通过抽象类定义契约、构造器链确保初始化安全。

明确“is-a”关系,避免为复用而继承
继承的本质是语义上的归属,不是功能上的搬运。比如 Admin 是 User,FileInputStream 是 InputStream,这种天然的层级关系才适合用 extends。如果只是为了调用几个方法就让一个类继承另一个,反而会引入不必要的耦合和意外行为。
- 反例:让
ReportGenerator继承DatabaseConnection——它并不“是一个”连接,只是“用到”连接 - 正解:用组合(has-a)代替继承,把
DatabaseConnection作为字段注入
用抽象类定义契约,留出扩展点
稳固的类库往往以抽象类为骨架,而非具体实现类。抽象类可以封装共用逻辑(如日志、校验、模板流程),同时用 abstract 方法强制子类实现关键行为。这样既保证结构统一,又保留定制自由。
- 例如:
AbstractService提供通用的execute()模板,子类只专注重写doWork() - 抽象类可含构造器,用于初始化共享状态(如配置、线程池),子类实例化时自动触发
控制访问权限,保护父类实现细节
父类不是越“开放”越好。过度暴露 protected 成员或非 final 方法,会让子类无意中依赖内部实现,一旦父类重构就容易崩。稳固的设计倾向“窄接口、宽实现”:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 属性尽量
private,通过protected final方法提供受控访问 - 关键流程方法设为
final(如模板方法中的主干),防止子类破坏整体逻辑 - 非必要不暴露
protected字段——宁可用protectedgetter,也不直接给字段
配合构造器链,确保初始化安全
继承体系下的对象创建必须可控。父类构造器应完成自身必需的初始化,子类通过 super(...) 显式衔接。尤其当父类无默认构造器时,子类必须显式调用,否则编译失败——这其实是种保护机制。
立即学习“Java免费学习笔记(深入)”;
- 抽象基类可定义带参构造器(如传入配置对象),子类在构造时就必须提供上下文
- 避免在构造器中调用
override方法——此时子类字段尚未初始化,易出空指针 - 若需延迟初始化,改用
init()模板方法,在构造完成后由框架统一触发

















