java不可变类需声明为final、字段全用final修饰并在构造器中初始化,对可变对象引用做防御性拷贝,getter返回不可变视图或副本,杜绝setter及任何修改入口。

在 Java 中设计不可变类,核心是让对象一旦创建,其状态就无法被外部修改。这不仅能避免并发问题,还能提升代码可读性和安全性。
用 final 修饰类、字段和方法
声明类为 final,防止被继承后通过子类破坏不可变性;所有字段必须是 final,确保初始化后不能重新赋值;如果提供 getter 方法,也建议设为 final(虽非强制,但可避免子类重写)。
- 类声明:
public final class Person { ... } - 字段声明:
private final String name;、private final int age; - 避免提供 setter 或任何修改字段的方法
确保构造过程完成所有状态初始化
所有字段必须在构造器中一次性赋值,且不能留空或延迟初始化。若字段是对象引用(如 List、Date),还需防止外部持有其引用后间接修改。
- 不要在构造器中直接赋值传入的可变对象引用,例如:
this.dates = dates;是危险的 - 应做防御性拷贝:
this.dates = new ArrayList(dates);或使用Collection.unmodifiableList(...) - 对基本类型和
String、Integer等不可变包装类,直接赋值即可
返回不可变视图而非原始引用
getter 方法不能返回内部可变对象的原始引用,否则调用方可能修改它。应返回副本或只读包装。
- 错误示例:
public List<string> getHobbies() { return hobbies; }</string> - 正确做法:
public List<string> getHobbies() { return Collections.unmodifiableList(hobbies); }</string> - 对于数组,用
Arrays.copyOf(...)返回副本;对于时间类如java.util.Date,返回new Date(date.getTime())
避免在类中暴露可变状态的访问途径
除了字段和 getter,还要检查是否无意中提供了其他修改入口,比如公开内部集合、允许注册回调、或提供“builder-like”方法。
- 不提供
addHobby(String)这类方法 - 不返回
this(避免链式调用破坏不可变性) - 内部使用的工具类或缓存字段也应是 final 且不可变,或仅用于计算、不参与状态表达
不可变类不是靠“禁止修改”来实现的,而是靠“没有修改的可能”来保障。只要切断所有外部修改路径,并对可变组件做好封装与复制,就能真正守住对象的状态边界。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











