//案例一 public static void main(String[] args) { Listlist = new ArrayList<>(); list.add("1"); list.add("2"); for (String item : list) { if ("1".equals(item)) { list.remove(item); } } } //运行不报错
//案例二 public static void main(String[] args) { Listlist = new ArrayList<>(); list.add("1"); list.add("2"); for (String item : list) { if ("2".equals(item)) { list.remove(item); } } } //运行报错Exception in thread "main" java.util.ConcurrentModificationException
二、javap反编译后字节码分析
public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: new #2 // class java/util/ArrayList 3: dup 4: invokespecial #3 // Method java/util/ArrayList."":()V 7: astore_1 8: aload_1 9: ldc #4 // String 1 11: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 16: pop 17: aload_1 18: ldc #6 // String 2 20: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 25: pop 26: aload_1 27: invokeinterface #7, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator; 32: astore_2 33: aload_2 34: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z 39: ifeq 72 42: aload_2 43: invokeinterface #9, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object; 48: checkcast #10 // class java/lang/String 51: astore_3 52: ldc #6 // String 2 54: aload_3 55: invokevirtual #11 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 58: ifeq 69 61: aload_1 62: aload_3 63: invokeinterface #12, 2 // InterfaceMethod java/util/List.remove:(Ljava/lang/Object;)Z 68: pop 69: goto 33 72: return
21-25行:java编译器把for循环编译成List.iterator,然后通过Iterator.hasNext,Iterator.next遍历,然后checkcast指令String类型校验
三、源码分析
1. 调用ArrayList.iterator(),返回Iterator对象
2. 标记5是 Iterator对象的remove(),标记6是 ArrayList的remove()
3. cursor是Iterator当前指针,lastRet是Iterator上次遍历的指针,modCount是ArrayList的变更次数,当add(1),add(2),remove(1)时,modCount=3
案例一分析:
1. add(1),add(2),for遍历 : modCount=2,expectedModCount=2,cursor=0,size=2
2. Iterator.hasNext():返回true
3. Iterator.next():标记3的checkForComodification()校验成功,返回字符串“1”
4. equals=true,调用标记6的ArrayList的remove():modCount=3,expectedModCount=2,cursor=1,size=1
5. Iterator.hasNext():返回false,退出循环
总结:根本就没有遍历第二个字符串“2”
案例二分析:
1. add(1),add(2),for遍历 : modCount=2,expectedModCount=2,cursor=0,size=2
2. Iterator.hasNext():返回true
3. Iterator.next():标记3的checkForComodification()校验成功,返回字符串“1”
4. equals=false:modCount=2,expectedModCount=2,cursor=1,size=2
5. Iterator.hasNext():返回true
6. Iterator.next():标记3的checkForComodification()校验成功,返回字符串“2”
7. equals=true,调用标记6的ArrayList的remove():modCount=3,expectedModCount=2,cursor=2,size=1
8. Iterator.hasNext():返回true
9. Iterator.next():标记3的checkForComodification()校验失败,modCount != expectedModCount抛异常ConcurrentModificationException
总结:
1. ArrayList.remove()方法不会更新expectedModCount,cursor,只更改了原数组,size,modCount等数据,由于数据不一致导致校验失败。
2. Iterator.remove()方法会更新原数组,size,modCount等数据。