增强for循环对Collection调用Iterator,对数组直接使用索引;遍历int[]无装箱和对象分配,遍历ArrayList则隐式调用iterator().next()并执行hasNext()检查。

增强for循环实际调用的是Iterator还是数组索引
Java的for-each循环不是语法糖那么简单——它会根据遍历目标类型走完全不同的底层路径。对Collection子类(如ArrayList、HashSet)会编译为Iterator调用;对普通数组则直接展开为带索引的for循环,不创建任何对象。
这意味着:遍历int[]时没有装箱开销、没有Iterator实例分配;而遍历ArrayList<integer></integer>时,每次迭代都隐式调用iterator().next(),且hasNext()检查不可省略。
- 数组场景下,
for-each和手动写for (int i = 0; i 生成的字节码几乎一致 -
Collection场景下,编译器会插入iterator()调用,并在循环体前后生成hasNext()和next()逻辑 - 自定义类要支持
for-each,必须实现Iterable<t></t>接口,否则编译报错:Can only iterate over an array or an instance of java.lang.Iterable
为什么遍历过程中修改集合会抛ConcurrentModificationException
这不是for-each本身的问题,而是底层Iterator的fail-fast机制在起作用。当用for-each遍历ArrayList时,实际使用的是其内部类Itr,它持有一个expectedModCount字段,初始化时等于集合的modCount。只要集合结构被修改(增/删元素),modCount就自增,下次next()前会校验二者是否一致。
- 即使你没显式调用
iterator.remove(),只要在循环体内执行list.remove(x)或list.add(y),下一轮迭代就会触发ConcurrentModificationException - 数组遍历不会抛这个异常,因为不涉及
modCount校验——但注意,改数组长度不影响遍历,改元素值当然可以 - 若需边遍历边删,应改用
Iterator.remove(),这是唯一安全的方式
for-each无法获取索引或修改元素值的根源
for-each只提供“读取当前项”的能力,不暴露索引变量,也不允许对循环变量赋值来改变原集合/数组内容。这是因为它的设计目标是简化遍历逻辑,而非替代传统for的控制力。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
- 对数组:循环变量是副本,
for (String s : strs) { s = "new"; }完全不影响strs中的字符串引用 - 对集合:同理,
s只是从next()返回的引用拷贝,重新赋值不会更新集合内元素 - 需要索引?老实用
for (int i = 0; i ;需要修改元素?数组可用<code>arr[i] = ...,List可用list.set(i, ...) - 想一行写出带索引的遍历?别硬套
for-each,Java 16+的Stream.iterate或第三方库如Guava的IntStream.range更合适
性能差异在哪:什么时候该避开for-each
绝大多数情况下for-each和手写循环性能无差别,但两类场景值得警惕:
- 遍历原始类型数组(
int[]、double[])时,如果循环体极轻(比如只做加法),JIT可能对传统for做更好优化,for-each因隐藏了索引计算反而略慢——不过差距通常在纳秒级,除非压测瓶颈在此 - 遍历
LinkedList时,for-each走Iterator是O(1)逐个移动,但若你误以为它像ArrayList一样支持随机访问,进而试图用get(i)模拟索引操作,就会掉进O(n²)陷阱 - Android开发中,
for-each在旧版本Dalvik上会产生额外Iterator对象,增加GC压力;现在ART已优化,但仍有团队保留“避免for-each”的旧规
真正影响性能的往往不是语法形式,而是你是否清楚自己遍历的是什么结构、它怎么存、怎么查。

















