平时大家for循环应该用的不少,特别是增强for循环,简单快捷。但是在增强for中做删除操作,却会抛出java.util.ConcurrentModificationException,一起来看下。

上面的代码,在for循环执行完if中的remove,遍历下一个元素时便会抛出java.util.ConcurrentModificationException。到底在for (String s : list)中发生了什么呢。

ArrayList中有一个内部类Itr,它继承了Iterator接口。当第一次遍历增强for循环时,会创建一个Itr对象,注意下图红框的部分,变量modCount属于ArrayList,用来记录ArrayList被修改的次数,赋值给了Itr类的变量expectedModCount。

然后依次调用Itr的hasNext()和next()方法,取出ArrayList中的元素赋值给for中的变量,注意红框的方法checkForComodification()。

当执行list.remove(s)时,实则调用其内部的fastRemove(index)做的删除操作,同时modCount++,但是并没有重新赋值给Itr类的变量expectedModCount。那么,当遍历下一个元素调用checkForComodification()方法时,if中的条件就会成立,然后就会抛出ConcurrentModificationException异常。

既然增强for循环中的remove操作会抛异常,那么在普通for循环和迭代器循环中做remove也会抛异常吗?

普通for循环

普通for循环调用的是remove(int index)方法,不会抛异常,但是需要注意,

1. 如果将for中的i < list.size()替换成i < length,会抛出IndexOutOfBoundsException

2. 在list.remove(i)后,下一次遍历前,此时i表示第i+1个元素

迭代器循环

迭代器循环调用的是Itr类的remove(int index)方法,不会抛异常,原因是其内部也是调用的ArrayList的remove(int index)方法,但是在之后,有给expectedModCount重新赋值。

所以

增强for循环,实际上还是迭代器遍历,但是remove操作并没有同步变量,会导致异常;普通for虽然没有异常,但是在remove后可能会忽略下标+1而出错;如果要在遍历时删除,最安全就是用迭代器。

Java基础之增强for循环的更多相关文章

  1. 【Java基础】增强for循环要注意陷阱

    什么是增强for循环 增强for循环是一种简单模式的for循环,为了方便数组和集合的遍历而存在. int[] arr = new int[]{1, 2, 3, 4, 5, 6}; for (int a ...

  2. java基础39 增强for循环(也叫foreach循环)

    增强for循环是jdk1.5出现的新功能 1.增强for循环的作用 简化了迭代器的书写格式(注意:增强for循环底层还是使用了迭代器遍历) 2.增强for循环的格式 for(数据类型 变量名:遍历的目 ...

  3. Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用

    在perference 加content Assist 可以设置快捷键 透视图与视图 透视图:Debug和java主窗口 视图:每一个小窗口就是视图 高版本的java可运行低版本的java版本 常见的 ...

  4. Java中的增强for循环

    增强 for 循环 1. 增强的 for 循环对于遍历 Array 或 Collection 的时候相当方便. import java.util.*; public class Test { publ ...

  5. Java中的增强 for 循环 foreach

    foreach 是 Java 中的一种语法糖,几乎每一种语言都有一些这样的语法糖来方便程序员进行开发,编译期间以特定的字节码或特定的方式来对这些语法进行处理.能够提高性能,并减少代码出错的几率.在 J ...

  6. 【Java基础】【04循环语句&方法】

    04.01_Java语言基础(循环结构概述和for语句的格式及其使用) A:循环结构的分类 for,while,do...while B:循环结构for语句的格式: for(初始化表达式;条件表达式; ...

  7. java基础:switch语句应用,循环的详细介绍以及使用,附练习案列

    1. switch语句 1.1 分支语句switch语句 格式 switch (表达式) { case 1: 语句体1; break; case 2: 语句体2; break; ... default ...

  8. Java基础之分支结构循环结构

    流程控制语句if(分支结构) 流程控制:流程就是指代码运行过程.控制就是说什么场景可以执行,什么场景不能执行. 1.if语句第一种形式 格式:if(表达式){      执行的语句:     } 2. ...

  9. 9.Java基础_for/while/do-while循环

    /* for循环(同C++) 初始化变量的作用域为循环体 出了循环体,初始化的局部变量消失 for(初始化;条件判断;条件控制){ 循环体; } while循环 while(条件判断){ 循环体; } ...

随机推荐

  1. Web应用程序和网站的区别

    1项目就是一个应用程序.在VS中查看的时候,项目中建立的一般处理程序,有两个文件,网站只有一个.写个代码测试,发现在代码层次上没有2再有就是项目中的一般处理程序有命名空间,而网站中的没有.WEB网站每 ...

  2. JavaScript 中的12种循环遍历方法

    原文:JavaScript 中的12种循环遍历方法 题目:请介绍 JavaScript 中有哪些循环和遍历的方法,说说它们的应用场景和优缺点? 1.for 循环 let arr = [1,2,3];f ...

  3. mvn 命令在command prompt无法识别

    Download maven from this website: https://maven.apache.org/download.cgi 解压binary包后放到一个位置,比如C:\apache ...

  4. Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化

    原文:Win8 Metro(C#)数字图像处理--2.58双峰法图像二值化  [函数名称]   双峰法图像二值化 WriteableBitmap  PeakshistogramThSegment( ...

  5. SqlServer 更改复制代理配置文件参数及两种冲突策略设置

    原文:SqlServer 更改复制代理配置文件参数及两种冲突策略设置 由于经常需要同步测试并更改代理配置文件属性,所以总结成脚本,方便测试. 可更新订阅的冲突策略有两种情况:一是在发布中冲突,即订阅数 ...

  6. OpenGL与Directx的区别

    OpenGL 只是图形函数库. DirectX 包含图形, 声音, 输入, 网络等模块. 单就图形而论, DirectX 的图形库性能不如 OpenGL OpenGL稳定,可跨平台使用.但 OpenG ...

  7. MJPhotoBrowser 用法

    一.使用方法:   #import "MJPhotoBrowser.h" #import "MJPhoto.h"   - (void)tapPhoto:(UIT ...

  8. windows下nginx的安装和使用

    LNMP的安装与配置 windows下的nginx安装和使用 1.1 去官网下载相应的安装包:http://nginx.org/en/download.html 1.2 解压后进入PowerShell ...

  9. 【转】Mysql索引最左匹配原则理解

    作者:沈杰 链接:https://www.zhihu.com/question/36996520/answer/93256153来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  10. Spring注解?啥玩意?

    目录 基础概念:@Bean 和 @Configuration 使用AnnotationConfigApplicationContext 实例化Spring容器 简单的构造 使用register注册IO ...