• 一种较为隐蔽ConcurrentModificationException情形


    ConcurrentModificationException是遍历过程中修改list而抛出的错误。就像前面分析的,单线程时这种错误主要是因为使用forEach造成:遍历一个拷贝,修改原始list,造成的。简单的大家都知道,这里要说一种比较隐蔽的出错方式:

     1 public class ExceptionTest{
     2 
     3     private List<String> list = new ArrayList<>();
     4 
     5     public ExceptionTest(){
     6         for(int i=0;i<9;i++){
     7             list.add("string"+i);
     8         }
     9     }
    10     
    11     public void throwExceptions(){
    12         List<List<String>>  listList = new ArrayList<>();
    13         listList.add(list.subList(0,3));
    14         listList.add(list.subList(3,6));
    15         listList.add(list.subList(6,8));
    16         Iterator<List<String>> it1 = listList.iterator();
    17         while(it1.hasNext()){
    18             List<String> l = it1.next();
    19             Iterator<String> it = l.iterator();
    20             while(it.hasNext()){
    21                 String str = it.next();
    22                 if(str.endsWith(("5"))){
    23                     it.remove();
    24                 }
    25             }
    26         }
    27     }
    28  }

    运行上面的代码还是会出错,虽然两层循环都用来Iterator。如果不仔细看很难发现这其中的原因。当你调试你会发现,删除以5结尾的字符串的时候,listList中的第一个子list会报错,而不是正在做修改的第二个子list。所以这个错误的来源不是两个遍历的本事,而是listList的初始化方式,可以看到13到16行,每个子列表使用的是list的subList方法。进一步查看subList代码可以发现。这个方法其实并未新建list而是返回了原理list的一个视图(其实索引):

    SubList(AbstractList<E> parent,
                    int offset, int fromIndex, int toIndex) {
                this.parent = parent;
                this.parentOffset = fromIndex;
                this.offset = offset + fromIndex;
                this.size = toIndex - fromIndex;
                this.modCount = ArrayList.this.modCount;
            }

    所以在修改第二个子list的时候回引起父列表(list)状态发生改变,虽然两层遍历看起来是正常的,但是他们却是在遍历和修改同一个list,因此会抛出ConcurrentModificationException异常。

    总结:有时候的异常并不是因为当前的步骤引起的,原因有可能来自于之前的某一步骤。

  • 相关阅读:
    C# 文字转声音
    Parameter配置文件获取
    反射动态创建不同的Processor
    程序代码记Log
    Dictionary序列化和反序列化
    HQueue:基于HBase的消息队列
    Angular系列----AngularJS入门教程05:双向绑定(转载)
    Angular系列----AngularJS入门教程04:迭代器过滤(转载)
    Angular系列---- AngularJS入门教程03:AngularJS 模板(转载)
    Angular系列----AngularJS入门教程02:静态模板(转载)
  • 原文地址:https://www.cnblogs.com/zziawanblog/p/5272255.html
Copyright © 2020-2023  润新知