modcount 是 java 中实现 fail-fast 迭代器机制的核心字段,需在集合类中声明为 protected transient int modcount = 0,并在所有结构性修改方法中严格执行一次 modcount++,迭代器通过比对 expectedmodcount 与 modcount 来检测并发修改并抛出 concurrentmodificationexception。

Java 中的 modCount 是实现 fail-fast 迭代器机制的核心字段,它不是强制要求,但若希望自定义集合类支持安全迭代(即在并发修改时及时抛出 ConcurrentModificationException),就必须规范地声明、维护和使用它。
明确 modCount 的语义与声明位置
modCount 表示集合被结构性修改的次数——即改变元素数量或破坏遍历一致性(如 add/remove/clear)的操作,不包括仅修改元素内容(如 set 元素值)的行为。
应在集合类中声明为:
protected transient int modCount = 0;
- protected:便于子类访问(如自定义 List 继承 AbstractList);
- transient:避免序列化时传递该运行时状态;
- 初始值为 0,表示未发生任何结构性修改。
在所有结构性修改方法中严格自增
每次执行真正改变集合结构的操作,必须且仅执行一次 modCount++。常见需更新的场景包括:
-
add(E e)、add(int index, E e) -
remove(Object o)、remove(int index) clear()-
retainAll(Collection>)、removeAll(Collection>) - 其他重写的、导致 size 变化或内部结构重组的方法(如自定义的
sort()若触发重排)
⚠️ 注意:单次调用只增 1,不可多次递增(例如在 remove 内部调用了两次底层删除逻辑却 increment 了两次,会导致迭代器误判)。
迭代器内部需同步捕获并校验 modCount
自定义迭代器(如 iterator() 返回的内部类)应:
- 构造时保存当前
modCount值为expectedModCount; - 在
next()、hasNext()、remove()、forEachRemaining()等关键操作前,调用校验方法; - 校验逻辑统一为:
if (modCount != expectedModCount) throw new ConcurrentModificationException(); -
remove()成功后,需同步更新expectedModCount = modCount,否则后续调用会立即失败
避免常见陷阱
以下行为会破坏 fail-fast 机制或引发误报:
- 在迭代过程中调用集合自身的
add()/remove()—— 这正是 modCount 设计要拦截的,应改用迭代器的remove(); - 子类重写结构性方法但遗漏
modCount++(最常见错误); - 将 modCount 声明为
public或提供 setter 方法,导致外部随意篡改; - 在非结构性操作(如
get(int)、contains(Object))中修改 modCount; - 多线程环境下未加同步,导致 modCount 自增丢失(注意:modCount 本身不解决线程安全,fail-fast 仅用于检测,非替代同步)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











