Java 为什么';编译器无法发现ConcurrentModificationException的某些原因
很明显,这段代码在迭代过程中修改了一个列表Java 为什么';编译器无法发现ConcurrentModificationException的某些原因,java,iterator,javac,Java,Iterator,Javac,很明显,这段代码在迭代过程中修改了一个列表 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();
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());
}
}
}
为什么编译器不能对此发出警告?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);
}
}
List List=newlinkedlist(Arrays.asList(“A”、“B”、“C”、“D”、“E”));
Iterator it=list.Iterator();
while(it.hasNext()){
String next=it.next();
如果(下一个等于(“D”)){
列表。删除(下一步);
}
}
另一方面,以下命令引发异常:
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);
}
}
List List=newlinkedlist(Arrays.asList(“A”、“B”、“C”、“D”、“E”));
Iterator it=list.Iterator();
while(it.hasNext()){
String next=it.next();
如果(下一个等于(“C”)){
列表。删除(下一步);
}
}
<代码> > p>编译器不考虑代码的逻辑,只有合法的。
例如:
public void explode(int i) {
System.out.println(1 / (i - i)); // always divide by zero
}
这将始终抛出一个算术异常
,但它编译得很好
您的代码是一个不太明显的例子。编译器了解Java语言。它不知道构成Java标准库的数千个类中的任何一个类的API契约(可能除了Java.lang
包中的一些类)。您不能使用\remove()
方法删除元素吗?@screenmutt OP故意使用List\remove
。OP:我真的不认为编译器应该能够处理这个问题,边缘情况可能是删除由递归方法遍历的集合
中的一个项,在该方法中您只知道使用集合#remove
。出于同样的原因,编译器在编译过程中不会尝试查找ArrayIndexOutOfBoundsException的可证明实例-这不是唯一的方法编译器处理这些语义问题的责任。因为有些集合允许在迭代时被修改。因为知道API中所有类的内部实现细节并不是编译器的工作。它的工作是检查代码的语法是否正确。您应该使用it.remove()
而不是list.remove()
,而且编译器不会警告您,因为这是运行时
异常。@VinceEmigh并解释原因。基本上,这是因为迭代器无法实现元素已被删除,其hasNext()
返回false,不允许next()
引发异常。