Featured image of post Java 一种 java.util.ConcurrentModificationException 异常原因

Java 一种 java.util.ConcurrentModificationException 异常原因

Java 一种 java.util.ConcurrentModificationException 异常原因

该文章用来记录java学习过程中看似应该不会发生的异常

我们有一个 Main.java 和 cn/pinsoftstd/Study.java,源代码如下:

Main.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import cn.pinsoftstd.study.Study;
public class Main {
    public static void main(String[] args) {
        Study study=new Study();
        study.printHelloWorld();
        study.addProgramming("XiaoMing");
        study.addProgramming("XiaoHong");
        study.addProgramming("LiJun");
        study.removeProgramming("LiJun");	//发生异常
        study.printProgramingNames(); 	
    }
}

cn/pinsoftstd/Study.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package cn.pinsoftstd.study;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * The class study provides an interface for developers to add and remove
 * the ones who are studying programming or not.
 * @author Program
 * @version 1.0
 */
public class Study {
    public Study(){

    }
    /** This prints "Hello World",which is the person who must print once
     * study a programming language.
     * @author Program
     */
    public void printHelloWorld(){
        System.out.println("Hello World");
    }
    /**
     * This method adds a person to the Study Programming category.
     */

    public Programming addProgramming(String name){
        Programming pr=new Programming(name);
        programmings.add(pr);
        return  pr;
    }
    /**
     * This method removes a person from the Study Programming category.
     */
    public  boolean removeProgramming(String name) {
       boolean removed = false;
        for (Programming pr : programmings) {
            if (pr.name.equals(name)) {
                programmings.remove(pr);	//发生异常
                removed = true;
            }
        }
        return removed;
    }
    /**
     * This method prints the names of people who are studying programming.
     */
    public void printProgramingNames(){
        for(Programming pr:programmings){
            System.out.println(pr.name);
        }
    }

    private ArrayList<Programming> programmings=new ArrayList<>();
    public  class Programming{
        private String name;
        public Programming(String name){
            this.name=name;
        }
        public String name(){
            return this.name;
        }
        public void printStudyingProgramming(){
            System.out.println("Study Programming:"+name);
        }
    }
}

自己写的时候感觉没有问题,结果运行的时候抛出了 java.ConcurrentModificationException 异常。异常代码为Main.java中的 study.printProgramingNames();,Study.java中的programmings.remove(pr);不科学

其实,是因为在 Java 中增强型for循环使用了迭代器(iterator)遍历,如果在遍历的时候使用了 study.printProgramingNames();,迭代器会检测到数组列表的变化,从而抛出java.util.ConcurrentModificationException 异常。

解决方法

  • 方法一:使用迭代器遍历programmings数组列表,不使用增强型for循环遍历。下面是修改后的代码:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 public  boolean removeProgramming(String name) {
        boolean removed=false;
        Iterator<Programming>it=programmings.iterator();
        while (it.hasNext()){	//使用迭代器遍历
            Programming pr=it.next();
            if(pr.name.equals(name)){
                it.remove();
                removed=true;
            }
        }
        return removed;
  }

方法二:通过遍历索引(index)来遍历数组列表programmings。下面是修改后的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public  boolean removeProgramming(String name) {
        boolean removed = false;
        for(int i=0;i<programmings.size();i++){
           if(programmings.get(i).name.equals(name)){
               programmings.remove(i);
               removed = true;
           }
       }
        return removed;
    }
Licensed under CC BY-NC-SA 4.0