fail-fast机制
fail-fast(快速失败)机制在Java集合中都存在,本文就ArrayList
分析。
fail-fast是什么?
先从ArrayList的官方解释看看:
1 | /** |
翻译:
在迭代器创建之后,集合有机构性修改,除非使用迭代器自身的add
,remove
动作,使用ArrayList上的方法对集合中数据进行任何操作
(包括查询和修改),
都会触发快速失败
机制,表现为抛出ConcurrentModificationExeception
异常…
迭代器的快速失败并不能保证,即存在有错误发生也没触发的情况,所以,不该依赖这个依赖异常来写程序,仅是用来检查程序是否有bug
通俗的个人理解:
快速失败机制,对于集合上的操作,比如查询,修改,若数据出现不确定的情况,便不再返回一个不确定的结果,而是直接抛出异常,让用户尽快
知道有错误发生了。符合程序的确定性
的原则。
例子:
遍历过程中使用ArrayList的方法删除元素,在下一次调用迭代器的next()方法时,抛出异常
1 | //初始一个集合并设置数据 |
Java中,若是使用增强型For,遍历集合类时,本质使用其内部的迭代器来遍历
1 | //形式2:增强型For的本质形式(去语法糖) |
正确用法
1 | //形式3,使用自身的迭代器删除,不会抛出异常 |
内部实现原理:
List类中有一个变量modCount
,记录当前集合结构性修改的次数,(比如增加元素,删除元素都会导致结构性修改),初始为0,在add(),
remove()方法中都会调用modCount++
。
迭代器Iterator中有一个变量expectedModCount
,用于跟踪List中的modCount
的值,正常情况下,这两个值是保持相等的,这样可保证
迭代器能够正确无误的遍历所有的元素。若是List自己的删除一个元素,ModCount
加1,而迭代器中的ExpectedModCount
并没有做修改,
迭代器调用next()
方法时,检查到两个值不相同,即抛出异常,表示迭代器已经无法保证正确遍历元素了。
若想要遍历中删除,就要使用该迭代器
自身的remove方法,该方法会修改expectedModCount
与modCount
相等。