这个异常产生的原因

时间:2022-12-27 20:54:40
//这是我随便测试写的一个ArrayList
import java.util.*;
public class TestL
{
    public static void main(String[] args)
    {
        List<Integer> myInt = new ArrayList<Integer>();
        List<Integer> sub = new ArrayList<Integer>();
        myInt.addAll(Arrays.asList(1,2,3,2,5,7,3));
        sub = myInt.subList(1,6);
        System.out.println(myInt);
        System.out.println(sub);
       // System.out.println(myInt.retainAll(sub));
       List<Integer> subCopy = new ArrayList<Integer>(sub);
       System.out.println(myInt.retainAll(subCopy));
       System.out.println(myInt);
    }
}
目前是运行正常的,但是把注释掉的那行+上会产生异常
请教这个异常的原因(本人感觉是不是涉及到了内部的指针问题)

6 个解决方案

#1


抛出ConcurrentModificationException异常

当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 

例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不明确的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。 

注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。 

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。 

#2


请问List  <Integer>,这种书写方式,JDK1.4支持么?

#3


不支持的!!! 1楼的学习了!!

#4


找到答案了谢谢大家没注意api帮助!
The iterators returned by this class's iterator and listIterator methods are fail-fast: if list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

#5


补充:
在API文档中:
 List<E> subList(int fromIndex,  int toIndex)
    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和 toIndex 相等,则返回的列表为空)。返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。
此方法省去了显式范围操作(此操作通常针对数组存在)。通过传递 subList 视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围: 

            list.subList(from, to).clear();
 可以对 indexOf 和 lastIndexOf 构造类似的语句,而且 Collections 类中的所有算法都可以应用于 subList。
    如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。

其中有一段话可以看出与一楼有联系的东西:
     如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。
因为用subList得到的只是一个视图,是一个对列表的内部结构的引用,如果有增加、删除的操作就会产生异常(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果),而retainAll是删除操作,所以你的程序才会抛出ConcurrentModificationException异常。我是这么做的:
 sub   = new ArrayList<Integer>(  myInt.subList(1,6)); 就没有出异常了。

#6


明白了

#1


抛出ConcurrentModificationException异常

当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 

例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不明确的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。 

注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。 

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。 

#2


请问List  <Integer>,这种书写方式,JDK1.4支持么?

#3


不支持的!!! 1楼的学习了!!

#4


找到答案了谢谢大家没注意api帮助!
The iterators returned by this class's iterator and listIterator methods are fail-fast: if list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

#5


补充:
在API文档中:
 List<E> subList(int fromIndex,  int toIndex)
    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和 toIndex 相等,则返回的列表为空)。返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。
此方法省去了显式范围操作(此操作通常针对数组存在)。通过传递 subList 视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围: 

            list.subList(from, to).clear();
 可以对 indexOf 和 lastIndexOf 构造类似的语句,而且 Collections 类中的所有算法都可以应用于 subList。
    如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。

其中有一段话可以看出与一楼有联系的东西:
     如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。
因为用subList得到的只是一个视图,是一个对列表的内部结构的引用,如果有增加、删除的操作就会产生异常(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果),而retainAll是删除操作,所以你的程序才会抛出ConcurrentModificationException异常。我是这么做的:
 sub   = new ArrayList<Integer>(  myInt.subList(1,6)); 就没有出异常了。

#6


明白了