这是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];
    }


另一个线程可以进入那里。只有当我们拥有自己对要使用的数组的引用(一旦完成最后的**行)时,我们知道引用不会更改(因为它是本地的)。

10-07 16:59