使用for(Object obj:list)进行循环ArrayList时,如果循环删除list中的元素则会抛出 ConcurrentModificationException异常,如下图:
通过分析错误堆栈我们可以发现使用 for(Object obj:list) 进行循环时,实际上是调用List迭代器(iterator)的next方法进行循环(AbstractList类中的Itr内部类的next方法):
这时,next方法的第一行会对ArryList做校验,如果校验不通过,则抛出ConcurrentModificationException异常
checkForComodification方法:
该方法实际上是对modCount和expectedModCount变量进行比较,如果不同,则抛出异常。
这里涉及到两个变量:
modCount:AbstractList类成员变量。记录List结构变化的次数,每次改变list结构时(add,remove,trimToSize等)都会加1
expectedModCount:Itr(AbstractList类的迭代器)类成员变量,初始时和modCount相等:
了解这两个变量后我们就会发现,for循环中调用的remove方法是ArrayList的remove方法会对modCount变量加1,但expectedModCount变量并未改变。这样,在第二次循环时调用迭代器的next方法就会校验出错。
所以,如果需要对list进行循环删除时要使用迭代器,并调用迭代器的remove方法。