java不可变类设计目标是对象创建后状态永久不可更改,从而天然线程安全:需满足四点——类为final、字段全final、构造完成初始化且不逸出this、不提供修改方法;对可变字段须做防御性拷贝或使用不可变容器。

Java 中不可变类的设计目标很明确:对象一旦创建,状态就永远不可更改。这种设计天然规避了多线程环境下的竞态条件,不需要同步、锁或 volatile,就能保证线程安全。
核心设计原则
要真正实现不可变,必须同时满足以下四点:
- 类声明为 final:防止被继承后通过子类破坏不可变性(如重写方法、添加可变字段)
- 所有字段用 final 修饰:确保引用不可重新赋值;若字段是对象(如 List、Map),还需保证其内容也不可变
- 构造函数完成全部初始化:不暴露 this 引用(避免逸出),不依赖外部可变对象的浅拷贝
- 不提供任何修改状态的方法:禁止 setter、clear、add、set 等;只提供 getter 和返回新对象的“操作方法”(如 deposit() 返回新账户)
处理可变成员字段的细节
final 只能保证引用不变,不能阻止内部状态改变。比如 final List
正确做法是:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 对集合类字段,在构造时用 Collections.unmodifiableList() 等包装
- 或使用 Guava 的 ImmutableList.copyOf()、JDK9+ 的 List.of()
- 若字段是自定义对象,该对象本身也必须是不可变类
为什么能天然线程安全
不可变类的线程安全性不是靠机制“保障”的,而是由设计逻辑直接排除了问题根源:
- 没有共享可变状态 → 没有竞态条件(Race Condition)
- final 字段在正确构造前提下,对其他线程立即可见(JMM 提供的 happens-before 保证)
- 无需同步,无锁开销,无死锁风险,读操作完全并行
- 可安全发布(safe publication):只要对象构造完成,任意线程拿到它的引用,看到的状态就是一致且完整的
典型应用与注意事项
常见不可变类包括 String、Integer、LocalDate、BigDecimal,以及你自己设计的配置类、DTO、值对象等。
使用时注意:
- 频繁修改场景下会创建大量临时对象,需权衡内存与 GC 压力
- 可配合结构共享(如持久化数据结构)或对象池缓解开销
- 不要为了“不可变”而牺牲清晰性——例如嵌套过深的 builder 或泛型参数反而降低可读性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










