java中不可变对象需满足:字段私有final、可变组件防御性拷贝、getter返回不可修改视图或副本、无修改方法、构造器原子安全、类或方法final限制继承。

Java中不可变对象(Immutable Object)的核心在于:一旦创建,其状态就无法被修改。这并非仅靠把字段设为final就能实现,而是一套贯穿设计、构造、访问与继承控制的封装策略。
字段私有 + final 是基础,但不是全部
声明所有字段为private final能阻止外部直接赋值和子类重写,但若字段是可变类型(如ArrayList、Date、自定义非final类),仍可能通过引用间接修改内部状态。
- 对可变组件,在构造时做防御性拷贝(defensive copy),例如传入
List时用new ArrayList(original)或List.copyOf()(Java 10+) - 返回集合类字段时,不直接暴露原始引用,改用
Collections.unmodifiableList()等包装,或返回新副本 - 对于数组,构造时复制(
Arrays.copyOf()),getter中也复制后再返回
禁止提供任何修改状态的方法
不可变类中不能有setXxx()、add()、clear()等改变自身状态的方法;也不应暴露可变对象的引用供外部调用其修改方法。
- 连看似无害的“计算型”方法(如
trim()、toUpper())都应返回新对象,而非修改自身 - 避免在方法中意外修改内部缓存字段(如延迟初始化的
hashCode)——若需缓存,确保该字段本身不可变且线程安全(可用volatile配合CAS或使用AtomicInteger等)
构造过程必须原子且安全
对象在构造完成前不应被其他线程可见,否则可能看到部分初始化的状态。
- 所有字段应在构造器内一次性完成初始化,不依赖后续 setter 或回调
- 避免在构造器中调用可被子类覆写的非final方法(防止this逸出)
- 若需复杂构建逻辑,推荐配合静态工厂方法或Builder模式(Builder本身也应设计为不可变或一次性使用)
限制继承以保障不可变契约
若子类可覆写方法或添加可变字段,父类的不可变性将被破坏。
- 将类声明为
final是最直接的方式(如String、LocalDateTime) - 若必须支持继承,至少将所有方法设为
final,并确保所有字段仍满足不可变要求 - 避免提供受保护的构造器或字段,防止子类绕过封装逻辑
不可变性带来的线程安全、缓存友好、易于推理等优势,只有在封装细节上严谨把控才能真正落地。它不是语法技巧的堆砌,而是对“谁可以改变什么”这一问题的持续约束。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










