java中实现不可变类的核心是:所有字段私有且final、构造时完成初始化、不提供修改方法、对可变组件进行防御性拷贝、禁止继承。

Java 中实现不可变类的核心是:所有字段私有、不提供修改方法、构造时完成初始化、避免返回可变对象引用。只读属性本身不是 Java 语言特性,而是通过封装策略达成的“逻辑只读”效果。
用 private final 字段 + 无 setter 方法
这是最基础也最关键的一步。声明字段为 private final,确保实例创建后无法被重新赋值;同时不暴露任何 public setter 方法,防止外部修改状态。
- 所有字段必须用 final 修饰(基本类型或不可变引用)
- 构造器中完成全部字段初始化(不能留空或延迟赋值)
- 不要提供任何以
setXxx()命名的方法
防御性拷贝可变组件
如果类包含可变对象(如 ArrayList、Date、数组等),直接返回其引用会破坏不可变性。必须在 getter 中返回副本。
- 对数组:用
Arrays.copyOf()或新建数组复制 - 对集合:用
new ArrayList(original)或Collection.unmodifiableList()(注意后者仅防写,不防原集合变化) - 对可变类如
java.util.Date:在 getter 中 new 一个新实例并复制时间戳
不提供可变视图或泄露内部引用
即使字段是 final,若 getter 返回了内部可变对象的原始引用,外部仍可能修改它,导致对象状态意外改变。
- 避免直接返回私有集合字段(如
return this.list;) - 避免返回内部数组引用(如
return this.data;) - 若需暴露集合,优先使用不可变包装(如
List.copyOf(list),Java 10+)或明确说明“只读视图”
确保子类无法破坏不可变性
如果类可能被继承,子类可通过重写方法或添加可变字段绕过封装。稳妥做法是将类声明为 final。
- 加上 final class 修饰符,禁止继承
- 若必须允许继承,至少把所有方法设为 final,防止行为被篡改
- 避免在构造器中调用可被重写的方法(防止子类在父类初始化完成前访问未就绪状态)
不可变类不是靠语法强制“只读”,而是靠设计契约保证。只要坚持 final 字段、无修改入口、防御性拷贝、禁止继承这四点,就能可靠地构建真正不可变的对象。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











