collections.unmodifiablelist的remove()不触发fail-fast,而是直接抛出unsupportedoperationexception;因其装饰器类不维护modcount、所有修改方法立即抛异常,且迭代器也不校验并发修改。

在 Collections.unmodifiableList 上调用 remove() 方法时,**不会触发 fail-fast 机制**,而是直接抛出 UnsupportedOperationException —— 这是明确的、静态的、由装饰器类主动抛出的异常,与 fail-fast 无关。
为什么不是 fail-fast?
fail-fast 是指迭代器(Iterator)在检测到集合结构被并发修改(如非迭代器自身的 remove())时,主动抛出 ConcurrentModificationException。它依赖于 modCount 和 expectedModCount 的校验,只存在于支持快速失败的可变集合(如 ArrayList、HashMap)的迭代器中。
unmodifiableList 返回的是一个内部静态类 UnmodifiableRandomAccessList(或其父类 UnmodifiableList),它:
- 不维护
modCount字段 - 所有修改方法(
add、remove、set等)都直接throw new UnsupportedOperationException() - 其
iterator()返回的迭代器也继承自UnmodifiableList,同样不检查modCount,所有修改操作(如iterator.remove())也直接抛UnsupportedOperationException
remove() 调用时的实际执行路径
以 unmodifiableList.remove(0) 为例:
- 调用的是
UnmodifiableList.remove(int index) - 该方法体只有一行:
throw new UnsupportedOperationException(); - 根本不会访问底层数组、不会读取
modCount、不会进入任何循环或校验逻辑
所以不存在“抛错顺序”问题 —— 它在方法入口就立即终止,没有中间步骤。
对比:真正的 fail-fast 场景
只有当你对原始可变列表(如 new ArrayList())进行迭代的同时,用非迭代器方式修改它,才会触发 fail-fast:
Iterator<string> it = list.iterator();</string>it.next();list.remove(0); // 修改底层结构it.next(); // 此时抛 ConcurrentModificationException
这个异常发生在迭代器的 checkForComodification() 调用中,属于运行时动态检测,和 unmodifiableList 的静态拒绝有本质区别。
小结
Collections.unmodifiableList 的 remove() 是防御性设计:不尝试执行、不延迟报错、不依赖状态校验 —— 它用最直接的方式拒绝所有修改请求。因此,它既不参与、也不体现 fail-fast 行为。想看到 ConcurrentModificationException,必须使用可变集合 + 迭代器 + 并发修改的组合。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











