Java继承需严格遵守里氏代换原则:方法重写须保持签名一致、异常范围不扩大、前置条件不加强、后置条件不削弱;private成员不可见,protected为受控扩展接口;构造器须显式调用super();模板方法模式用final+abstract固化流程契约;Square继承Rectangle是典型违反契约的反例,应优先组合而非继承。

Java 中继承维护基类与子类的契约,核心在于尊重父类已定义的行为规范,确保子类在替换父类时不会破坏原有逻辑——这正是里氏代换原则(Liskov Substitution Principle, LSP)的要求。
用方法重写遵守行为契约
子类重写父类方法时,不能随意改变其语义或前提/后置条件:
- 方法签名必须一致(名称、参数类型与顺序、返回类型可协变)
- 不能抛出比父类方法更宽泛的异常(例如父类声明 throws IOException,子类只能抛 IOException 或其子类,不可抛 Exception)
- 前置条件不能加强(子类方法不能要求比父类更严格的输入),后置条件不能削弱(子类执行后应保证至少和父类同等程度的状态承诺)
- 避免重写 final 方法或 static 方法(后者实际是隐藏,不是重写)
避免破坏封装与访问契约
父类通过访问修饰符划定“可继承边界”,子类需在其范围内行事:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- private 成员虽被继承(占用内存),但不可见、不可直接访问——子类应通过父类提供的 public/protected 方法间接操作
- protected 是设计给子类用的“受控接口”,子类可访问并合理扩展,但不应绕过其设计意图(如擅自修改父类内部状态而不触发对应逻辑)
- 构造器不被继承,子类必须显式调用 super(...),且须放在首行——这是保障父类初始化契约的关键步骤
用抽象与模板方法固化契约结构
当父类需要强制子类遵循某种流程时,可结合 abstract 和 final 构建稳定骨架:
立即学习“Java免费学习笔记(深入)”;
- 将不变逻辑封装在 final 方法中(如 start()),子类无法覆盖,确保行为一致性
- 把变化点定义为 abstract 方法(如 accelerate()),由子类实现,但调用时机和上下文由父类控制
- 这种“模板方法模式”让子类只负责“做什么”,而父类决定“何时做、怎么做”,从结构上守住契约
警惕违反契约的典型反例
一个经典陷阱是让 Square 直接继承 Rectangle:
- 父类 setHeight() 和 setWidth() 允许独立设置,子类若重写为同步修改两边,就违背了“能独立调整”的隐含契约
- 外部代码按 Rectangle 行为编写(比如只改高不改宽),在传入 Square 实例时就会出错
- 此时应优先考虑组合(Square 持有 Rectangle 引用并封装约束),而非继承

















