平时大家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. MVVMLight 实现指定Frame控件的导航

    原文:MVVMLight 实现指定Frame控件的导航 在UWP开发中,利用汉堡菜单实现导航是常见的方法.汉堡菜单导航一般都需要新建一个Frame控件,并对其进行导航,但是在MvvmLight框架默认 ...

  2. Win10中解决Prolific PL2303出现错误代码10的问题

    PL2303 是Prolific 公司生产的一种高度集成的RS232-USB接口转换器,在Win10中默认安装的驱动程序会出现错误代码10的问题,如下图所示: 下载Win10上可以用的PL2303驱动 ...

  3. 新浪API登录实例

    步骤一:添加网站 进入新浪微博开放平台,http://open.weibo.com/apps 进入“管理中心“,点击”创建应用”,选择“网页应用”,填写相应的信息后提交. 步骤二:Oauth2.0授权 ...

  4. mysql的命令行安装,忘记密码,密码重置问题

    1.下载,安装msi 2.在MYSQL安装目录下,新建data目录 3.进入MYSQL的安装目录下,新建一个默认配置文件my.ini [mysql] # 设置mysql客户端默认字符集 default ...

  5. 零元学Expression Blend 4 - Chapter 16 用实例了解互动控制项「Button」II

    原文:零元学Expression Blend 4 - Chapter 16 用实例了解互动控制项「Button」II 本章将教大家如何制作自己的Button,并以玻璃质感Button为实作案例. ? ...

  6. 【转载】动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)

    原文地址:https://www.cnblogs.com/westsoft/p/5936092.html 动态载入 DLL 动态载入方式是指在编译之前并不知道将会调用哪些 DLL 函数, 完全是在运行 ...

  7. 一个Demo让你掌握Android所有控件

    原文:一个Demo让你掌握Android所有控件 本文是转载收藏,侵删,出处:"安卓巴士"      下面给出实现各个组件的源代码: 1.下拉框实现--Spinner packag ...

  8. Android零基础入门第75节:Activity状态和生命周期方法

    前面两期我们学习了Activity的创建和注册.以及启动和关闭,也学会了重写onCraete方法,这些知识在实际开发中远远不够,还需要学习了解更多. 生命周期就是一个对象从创建到销毁的过程,每一个对象 ...

  9. MinGW版Qt如何搭建lua环境?(详细步骤)

    操作系统是windows,lua是Lua for Windows 5.1.4包含了这三个头文件 <ignore_js_op>  在.pro里加了includepath: <ignor ...

  10. 解析 Qt 字库移植并能显示中文 (上篇)

    原文http://mobile.51cto.com/symbian-272552.htm 本文介绍的是Qt 字库移植并能显示中文,需要的字体库文件,一般是多个.具体移植那一个,看你使用的字库是什么了, ...