这是ArrayList :: Itr的下一个方法
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
它包含一个if语句:
if (i >= elementData.length)
throw new ConcurrentModificationException();
我认为条件
i >= elementData.length
很少发生,除非用户调用trimToSize方法。而且我认为if语句是多余的,因为checkForComodification可以处理所有事情。我对吗?
最佳答案
不,不是。如果使用了另一个线程,使得在ArrayList
之后的trimTosize
checkForComodification();
...但在
Object[] elementData = ArrayList.this.elementData;
在此期间,
ArrayList.this.elementData
可能已更改(接收到新的数组引用)。因此,在将ArrayList.this.elementData
捕获到局部变量(elementData
)之后,检查数组中的索引是否正确是正确和必要的。代码完成后,它对要查找的数组有一个本地引用(elementData
)和一个索引为i
的本地变量。这时需要代码,以便抛出正确的异常(ConcurrentModificationException
)而不是ArrayIndexOutOfBounds
(如果在代码获取之前对ArrayList.this.elementData
的更改使索引无效)。例如,请注意
**
行: public E next() {
checkForComodification();
int i = cursor; // ***
if (i >= size) // ***
throw new NoSuchElementException(); // ***
Object[] elementData = ArrayList.this.elementData; // ***
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
另一个线程可以进入那里。只有当我们拥有自己对要使用的数组的引用(一旦完成最后的
**
行)时,我们知道引用不会更改(因为它是本地的)。