java中ConcurrentModificationException异常警告怎么解决

这篇文章主要介绍“java中ConcurrentModificationException异常警告怎么解决”,在日常操作中,相信很多人在java中ConcurrentModificationException异常警告怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java中ConcurrentModificationException异常警告怎么解决”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

成都创新互联主要为客户提供服务项目涵盖了网页视觉设计、VI标志设计、网络营销推广、网站程序开发、HTML5响应式网站建设公司手机网站制作设计、微商城、网站托管及网站建设维护、WEB系统开发、域名注册、国内外服务器租用、视频、平面设计、SEO优化排名。设计、前端、后端三个建站步骤的完善服务体系。一人跟踪测试的建站服务标准。已经为成都砂岩浮雕行业客户提供了网站制作服务。

异常分析

相信写过一些Java代码的人都遇到过这个异常,一般都是由以下代码引起的:

import java.util.List;
import java.util.ArrayList;

public class Test{
   public static void main(String[] args){
     List<String> list = new ArrayList<>();
     list.add("123");
     list.add("456");
     list.add("789");
     for(String obj : list){
         list.remove(obj);
     }
   }
}

上述代码最终会引发java.util.ConcurrentModificationException,那么为什么呢?首先我们将上述代码反编译,得到如下结果(如果对foreach语法糖比较了解可以忽略):

public class Test {
 public Test();
   Code:
      0: aload_0
      1: invokespecial #1                  // Method java/lang/Object."<init>":()V
      4: return
   LineNumberTable:
     line 4: 0

 public static void main(java.lang.String[]);
   Code:
      0: new           #2                  // class java/util/ArrayList
      3: dup
      4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
      7: astore_1
      8: aload_1
      9: ldc           #4                  // String 123
     11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     16: pop
     17: aload_1
     18: ldc           #6                  // String 456
     20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     25: pop
     26: aload_1
     27: ldc           #7                  // String 789
     29: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     34: pop
     35: aload_1
     36: invokeinterface #8,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     41: astore_2
     42: aload_2
     43: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
     48: ifeq          72
     51: aload_2
     52: invokeinterface #10,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     57: checkcast     #11                 // class java/lang/String
     60: astore_3
     61: aload_1
     62: aload_3
     63: invokeinterface #12,  2           // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z
     68: pop
     69: goto          42
     72: return
   LineNumberTable:
     line 6: 0
     line 7: 8
     line 8: 17
     line 9: 26
     line 10: 35
     line 11: 61
     line 12: 69
     line 13: 72
}

将上述代码翻译出来等价于下列代码:

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Test{
   public static void main(String[] args){
     List<String> list = new ArrayList<>();
     list.add("123");
     list.add("456");
     list.add("789");
     Iterator<String> iterator = list.iterator();
     while (iterator.hasNext()){
         String obj = iterator.next();
         list.remove(obj);
     }
   }
}

然后我们查看iterator.hasNext()源码,可以发现第一行调用了checkForComodification方法,我们查看这个方法:

final void checkForComodification() {
   if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}

modCount != expectedModCount这个条件成立的时候会抛出ConcurrentModificationException异常,那么这个条件是怎么成立的呢?

1、首先我们查看modCount的来源,可以发现modCount的值等于当前List的size,当调用List.remove方法的时候modCount也会相应的减1;

2、然后我们查看expectedModCount的来源,可以看到是在构造Iterator(这里使用的是ArrayList的内部实现)的时候,有一个变量赋值,将modCount 的值赋给了expectedModCount

3、最后当我们执行循环调用List.remove方法的时候,modCount改变了但是expectedModCount并没有改变,当第一次循环结束删除一个数据准 备第二次循环调用iterator.hasNext()方法的时候,checkForComodification()方法就会抛出异常,因为此时ListmodCount已经变为 了2,而expectedModCount仍然是3,所以会抛出ConcurrentModificationException异常;

解决方法

那么如何解决该问题呢?我们查看java.util.ArrayList.Itr(ArrayList中的Iterator实现)的源码可以发现,在该迭代器中有一个remove方法可以 删除当前迭代元素,而且会同时修改modCountexpectedModCount,这样在进行checkForComodification检查的时候就不会抛出异常了,该remove 方法源码如下:

public void remove() {
   if (lastRet < 0)
       throw new IllegalStateException();
   checkForComodification();

   try {
       ArrayList.this.remove(lastRet);
       cursor = lastRet;
       lastRet = -1;
       expectedModCount = modCount;
   } catch (IndexOutOfBoundsException ex) {
       throw new ConcurrentModificationException();
   }
}

其中ArrayList.this.remove(lastRet);这一行会改变modCount的值,而后边会同步的修改expectedModCount的值等于modCount的值;

现在修改我们开头的程序如下就可以正常运行了:

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Test{
   public static void main(String[] args){
     List<String> list = new ArrayList<>();
     list.add("123");
     list.add("456");
     list.add("789");
     Iterator<String> iterator = list.iterator();
     while (iterator.hasNext()) {
         System.out.println("移除:" + iterator.next());
         iterator.remove();
     }
   }
}

到此,关于“java中ConcurrentModificationException异常警告怎么解决”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!

新闻名称:java中ConcurrentModificationException异常警告怎么解决
文章网址:https://www.cdcxhl.com/article38/pcjspp.html

成都网站建设公司_创新互联,为您提供品牌网站设计网站内链标签优化品牌网站制作小程序开发网站改版

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

h5响应式网站建设