这是 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();
我认为除非用户调用trimToSize方法,否则很少会发生i >= elementData.length
的情况。而且我认为 if 语句是多余的,因为 checkForCommodification 可以处理所有事情。
我说得对吗?
最佳答案
不,不是。如果使用另一个线程,ArrayList
的 trimTosize
在之后使用
checkForComodification();
...但是之前
Object[] elementData = ArrayList.this.elementData;
ArrayList.this.elementData
在此期间可能已更改(收到新的数组引用)。因此,在将 ArrayList.this.elementData
抓取到局部变量 (elementData
) 中之后,检查数组中的索引是否有效是正确且必要的。 。代码完成此操作后,它将具有对其要查找的数组的本地引用 (elementData
) 和索引的本地变量 i
)。如果对 ArrayList.this.elementData
进行更改,则此时需要该代码才能引发正确的异常 (ConcurrentModificationException
),而不是 ArrayIndexOutOfBounds
在代码抓取之前,它使索引无效。
例如,请注意 **
行:
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];
}
其他线程可能会进入其中。只有当我们有了自己对要使用的数组的引用(最后一个 **
行完成后),我们才知道引用不会改变(因为它是本地的)。
关于java - ArrayList::iterator 中的 i >= elementData.length 是多余的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38239985/