immutablelist 因设计上彻底禁止修改,故无需快照复制,迭代器直接访问唯一稳定数据,天然 fail-safe;而 copyonwritearraylist 依赖写时复制,unmodifiablelist 仅包装接口,底层仍可变。

因为 ImmutableList 本身不可变,根本不存在“被修改”的可能,所以无需快照复制来隔离读写。
ImmutableList 的不可变性是根本前提
Guava 的 ImmutableList 在创建后,其内部数组和元素引用都完全固定。所有修改方法(add、remove、set)都直接抛出 UnsupportedOperationException,连结构变更的入口都被堵死。迭代器遍历的不是“副本”,而是唯一且稳定的真实数据——既然没人能改它,自然不需要额外复制一份来防修改。
与 CopyOnWriteArrayList 的本质区别
CopyOnWriteArrayList 是可变集合,靠“写时复制快照”实现读写分离;而 ImmutableList 是从设计上消灭了“写”的可能性:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 构造后状态永久锁定,无 modCount、无并发修改检测逻辑
- 不依赖运行时校验机制(如 expectedModCount),也不维护任何版本计数器
- 内存中只有一份数据,迭代器直接访问原始数组,零额外开销
fail-safe 在这里体现为“天然安全”
所谓 fail-safe,核心是“遍历时不怕修改”。对 ImmutableList 来说,这个“不怕”不是靠技术兜底,而是因为修改行为在编译期或运行初期就被彻底禁止:
- 多线程并发读取时,无需同步,不会出现竞态
- 遍历过程中即使有其他代码试图调用 add(),也只会立即失败,不会影响当前迭代状态
- 不存在“原集合被改导致快照过期”的问题,因为原集合永远不会变
对比 JDK 的 unmodifiableList 就更清楚
JDK 的 Collections.unmodifiableList() 只是包装一层只读接口,底层 ArrayList 仍可被原始引用修改——所以它既不是 fail-fast(不抛 ConcurrentModificationException),也不是真正 fail-safe(遍历时可能看到脏数据)。而 ImmutableList 是从源头切断所有修改路径,它的安全是静态的、确定性的。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










