为什么编译器没有发现 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 中的某些 类 =]包)。