为什么编译器没有发现 ConcurrentModificationException 的某些原因
Why doesn't the compiler spot certain causes of ConcurrentModificationException
很明显这段代码在迭代过程中修改了一个列表。
public class ArrayIterator {
public static void main(String[] args) {
List<String> list = new LinkedList<>(Arrays.asList("A","B","C","D","E"));
Iterator<String> it = list.iterator();
while (it.hasNext())
{
list.remove(it.next());
}
}
}
所以我们得到了预期的异常
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at ArrayIterator.main(ArrayIterator.java:15)
为什么编译器不能对此发出警告?
java.util.ConcurrentModificationException
是运行时异常。它可能(或可能不)发生。在某些情况下,您希望 remove()
在迭代集合时抛出此异常,但根据元素的数量和当前元素的位置,不会发生异常。
例如,以下不会抛出异常:
List<String> list = new LinkedList<String>(Arrays.asList("A", "B", "C", "D", "E"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String next = it.next();
if(next.equals("D")) {
list.remove(next);
}
}
另一方面,以下抛出异常:
List<String> list = new LinkedList<String>(Arrays.asList("A", "B", "C", "D", "E"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String next = it.next();
if(next.equals("C")) {
list.remove(next);
}
}
编译器不考虑代码的逻辑,只考虑是否合法。
例如:
public void explode(int i) {
System.out.println(1 / (i - i)); // always divide by zero
}
这总是会抛出一个 ArithmeticException
,但它编译得很好。
你的代码是一个不太明显的例子。
编译器知道 Java 语言。它不知道构成 Java 标准库的数千个 类 中任何一个的 API 合同(除了 [=10 中的某些 类 =]包)。
很明显这段代码在迭代过程中修改了一个列表。
public class ArrayIterator {
public static void main(String[] args) {
List<String> list = new LinkedList<>(Arrays.asList("A","B","C","D","E"));
Iterator<String> it = list.iterator();
while (it.hasNext())
{
list.remove(it.next());
}
}
}
所以我们得到了预期的异常
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at ArrayIterator.main(ArrayIterator.java:15)
为什么编译器不能对此发出警告?
java.util.ConcurrentModificationException
是运行时异常。它可能(或可能不)发生。在某些情况下,您希望 remove()
在迭代集合时抛出此异常,但根据元素的数量和当前元素的位置,不会发生异常。
例如,以下不会抛出异常:
List<String> list = new LinkedList<String>(Arrays.asList("A", "B", "C", "D", "E"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String next = it.next();
if(next.equals("D")) {
list.remove(next);
}
}
另一方面,以下抛出异常:
List<String> list = new LinkedList<String>(Arrays.asList("A", "B", "C", "D", "E"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String next = it.next();
if(next.equals("C")) {
list.remove(next);
}
}
编译器不考虑代码的逻辑,只考虑是否合法。
例如:
public void explode(int i) {
System.out.println(1 / (i - i)); // always divide by zero
}
这总是会抛出一个 ArithmeticException
,但它编译得很好。
你的代码是一个不太明显的例子。
编译器知道 Java 语言。它不知道构成 Java 标准库的数千个 类 中任何一个的 API 合同(除了 [=10 中的某些 类 =]包)。