以下代码按预期抛出java.util.ConcurrentModificationException:
public void test(){
ArrayList<String> myList = new ArrayList<String>();
myList.add("String 1");
myList.add("String 2");
myList.add("String 3");
myList.add("String 4");
myList.add("String 5");
for(String s : myList){
if (s.equals("String 2")){
myList.remove(s);
}
}
}
但是,下面的代码并没有抛出异常,而我希望它被抛出:
public void test(){
ArrayList<String> myList = new ArrayList<String>();
myList.add("String 1");
myList.add("String 2");
myList.add("String 3");
for(String s : myList){
if (s.equals("String 2")){
myList.remove(s);
}
}
}
区别在于第一个列表包含5个项目,而第二个列表包含3.使用的JVM是:
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
问题:为什么第二段代码不会抛出java.util.ConcurrentModificationException?
发布于 2019-04-18 08:23:09
从ArrayList.iterator()
实现中返回的迭代器我们显然都只使用检查来调用结构修改next()
,而不是调用hasNext()
。后者看起来像这样(在Java 8下):
public boolean hasNext() {
return cursor != size;
}
因此,在你的第二个情况下,迭代器“知道”,它的返回两个元素,并且该列表仅具有两个元素...所以hasNext()
刚刚返回false,我们从来没有最终调用next()
的第三次。
我认为这是一个实现细节 - 基本上检查没有尽可能严格。hasNext()
在这种情况下执行检查并抛出异常是完全合理的。
发布于 2019-04-18 09:20:38
另请注意ArrayList文档摘要的最后一段:
快速失败的迭代器会
ConcurrentModificationException
尽力而为。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应该仅用于检测错误。
如果您担心强制列表是只读的,请使用该Collections.unmodifiableList
方法,而不是检查ConcurrentModificationException,如上所述,不保证在所有相关情况下抛出。
https://stackoverflow.com/questions/-100006639
复制相似问题