ArrayList::iterator 中的 i >= elementData.length 是多余的吗?
is i >= elementData.length in ArrayList::iterator redundant?
这是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 可以处理所有事情。
我说得对吗?
假设您的意思是 "redundant" 而不是 "abundant",那么不,它不是。
window在调用checkForComodification()
之后有一个小的(微小的)数组的大小可以改变,因为另一个线程已经调整了数组的大小ArrayList
。发生这种情况的可能性非常小,但如果不存在此检查,next()
调用可能会抛出 ArrayIndexOutOfRangeException
.
不利的一面是 next()
代码不能保证检测到所有并发修改。如果某个其他线程在 checkForComodification()
调用之后设法将一个元素添加到列表中,则该修改将不会被检测到。
不,不是。如果使用另一个线程,使得 ArrayList
的 trimTosize
被使用 after the
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];
}
另一个线程可以进来。只有当我们对我们将要使用的数组有自己的引用时(一旦最后 **
行完成)我们知道引用不会改变(因为它是本地的)。
这是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 可以处理所有事情。
我说得对吗?
假设您的意思是 "redundant" 而不是 "abundant",那么不,它不是。
window在调用checkForComodification()
之后有一个小的(微小的)数组的大小可以改变,因为另一个线程已经调整了数组的大小ArrayList
。发生这种情况的可能性非常小,但如果不存在此检查,next()
调用可能会抛出 ArrayIndexOutOfRangeException
.
不利的一面是 next()
代码不能保证检测到所有并发修改。如果某个其他线程在 checkForComodification()
调用之后设法将一个元素添加到列表中,则该修改将不会被检测到。
不,不是。如果使用另一个线程,使得 ArrayList
的 trimTosize
被使用 after the
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];
}
另一个线程可以进来。只有当我们对我们将要使用的数组有自己的引用时(一旦最后 **
行完成)我们知道引用不会改变(因为它是本地的)。