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

因为 ImmutableList 本身不可变,根本不存在“被修改”的可能,所以无需快照复制来隔离读写。
ImmutableList 的不可变性是根本前提
Guava 的 ImmutableList 在创建后,其内部数组和元素引用都完全固定。所有修改方法(add、remove、set)都直接抛出 UnsupportedOperationException,连结构变更的入口都被堵死。迭代器遍历的不是“副本”,而是唯一且稳定的真实数据——既然没人能改它,自然不需要额外复制一份来防修改。
与 CopyOnWriteArrayList 的本质区别
CopyOnWriteArrayList 是可变集合,靠“写时复制快照”实现读写分离;而 ImmutableList 是从设计上消灭了“写”的可能性:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 构造后状态永久锁定,无 modCount、无并发修改检测逻辑
- 不依赖运行时校验机制(如 expectedModCount),也不维护任何版本计数器
- 内存中只有一份数据,迭代器直接访问原始数组,零额外开销
fail-safe 在这里体现为“天然安全”
所谓 fail-safe,核心是“遍历时不怕修改”。对 ImmutableList 来说,这个“不怕”不是靠技术兜底,而是因为修改行为在编译期或运行初期就被彻底禁止:
立即学习“Java免费学习笔记(深入)”;
- 多线程并发读取时,无需同步,不会出现竞态
- 遍历过程中即使有其他代码试图调用 add(),也只会立即失败,不会影响当前迭代状态
- 不存在“原集合被改导致快照过期”的问题,因为原集合永远不会变
对比 JDK 的 unmodifiableList 就更清楚
JDK 的 Collections.unmodifiableList() 只是包装一层只读接口,底层 ArrayList 仍可被原始引用修改——所以它既不是 fail-fast(不抛 ConcurrentModificationException),也不是真正 fail-safe(遍历时可能看到脏数据)。而 ImmutableList 是从源头切断所有修改路径,它的安全是静态的、确定性的。

















