【发布时间】:2015-04-18 22:10:23
【问题描述】:
为什么这段代码不抛出ConcurrentModificationException?它在迭代 Collection 时修改它,而不使用 Iterator.remove() 方法,即 the only safe way of removing。
List<String> strings = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String string : strings)
if ("B".equals(string))
strings.remove("B");
System.out.println(strings);
如果我将ArrayList 替换为LinkedList,我会得到相同的结果。但是,如果我将列表更改为("A", "B", "C", "D) 或只是("A", "B"),我会得到预期的异常。到底是怎么回事?如果相关,我正在使用jdk1.8.0_25。
编辑
我找到了以下链接
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078
相关部分是
简单的解决方案是在 AbstractList 中的 hasNext 中添加共修改检查,但这会使共修改检查的成本加倍。 事实证明,只在最后一次进行测试就足够了 迭代,这几乎不会增加成本。换句话说, hasNext 的当前实现:
public boolean hasNext() { return nextIndex() < size; }被这个实现取代:
public boolean hasNext() { if (cursor != size()) return true; checkForComodification(); return false; }不会进行此更改,因为 Sun 内部监管机构拒绝了它。正式裁决表明,这一变化“已经 证明了具有重大兼容性影响的潜力 在现有代码上。”(“兼容性影响”是该修复程序具有 有可能将沉默的不当行为替换为 ConcurrentModificationException。)
【问题讨论】:
-
因为
ConcurrentModificationException是在“尽力而为”的基础上抛出的 -
我喜欢 Sun 没有做出改变的原因是它可能会使一些糟糕的代码实际上开始抛出它应该抛出的异常
标签: java