java中继承不保证基类不变性,需通过private封装、父类掌控构造、避免可变引用暴露及慎用protected来保障;如私有字段+公共受控接口、super强制调用、返回不可变视图或副本、优先private+protected方法而非protected字段。

Java 中继承本身不直接“保证”基类的不变性,相反,它天然存在对基类状态的潜在影响风险。真正保障基类不变性的,不是继承机制本身,而是设计约束与访问控制的组合使用。
基类成员用 private 封装
父类中关键字段应声明为 private,禁止子类直接读写。这样即使子类继承了该字段,也无法绕过父类提供的公共接口去修改内部状态。
例如:
- 父类定义
private String id;,只通过getId()和受控的setId(String)暴露行为; - 子类无法在自身方法中执行
this.id = "xxx";,只能调用父类方法间接操作; - 这从语言层面切断了子类破坏父类内部一致性的最常见路径。
构造逻辑由父类完全掌控
父类构造方法负责初始化所有核心字段,且子类构造器必须显式或隐式调用 super(...)。这意味着:
- 父类可校验参数、抛出异常、设置默认值,确保对象创建时状态合法;
- 子类不能跳过或绕过父类初始化流程;
- 若父类构造器是
private或仅提供带参且无默认值的构造器,还能进一步限制子类实例化方式(配合工厂模式更稳妥)。
避免暴露可变内部对象引用
即使字段是 private,若返回的是可变对象(如 ArrayList、数组、自定义可变类),子类仍可能通过引用修改其内容。
正确做法包括:
- 返回不可变视图:如用
Collections.unmodifiableList(list); - 返回副本:
new ArrayList(this.internalList); - 使用不可变类型:如
String、LocalDateTime、ImmutableList(Guava)等。
谨慎使用 protected 成员
protected 字段或方法虽比 public 安全,但仍允许子类直接访问和修改——这实质上削弱了封装性。
建议:
- 优先将字段设为 private,仅提供 protected 的受控方法(如模板方法中的钩子);
- 若必须用 protected 字段,应在文档中明确说明其用途和修改约束;
- 考虑用 final 修饰不可变字段,防止子类在构造后重新赋值。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











