增强for循环是编译器提供的语法糖,遍历集合时自动调用Iterable.iterator()获取迭代器,并执行hasNext()和next()完成遍历;遍历数组则被转译为基于索引的传统for循环。

增强 for 循环(for-each)在 Java 中是语法糖,底层**自动调用对象的 Iterator 迭代器**,前提是该对象实现了 Iterable 接口。编译器在编译阶段就将其翻译为传统的 while + Iterator 模式。
编译器如何翻译增强 for 循环
当你写:
for (String s : list) {
System.out.println(s);
}
Java 编译器(javac)实际生成的字节码等价于:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}
也就是说,增强 for 循环本身不“持有”迭代器,而是每次循环前调用 list.iterator() 获取一个新迭代器(对集合而言),然后反复调用 hasNext() 和 next()。
立即学习“Java免费学习笔记(深入)”;
必须满足的条件:Iterable 接口
只有实现了 java.lang.Iterable 接口的类型才能用于增强 for 循环。该接口只定义了一个方法:
public interface Iterable<T> {
Iterator<T> iterator();
}
常见可遍历类型(如 ArrayList、LinkedList、HashSet、数组(特殊处理)、自定义类)都满足这一要求。其中:
- 集合类:直接实现
Iterable,iterator()返回对应迭代器(如ArrayList$Itr) - 数组:编译器特殊处理——不是靠实现
Iterable(数组类型本身没实现),而是编译期生成适配代码,内部转为基于索引的循环(但语义上仍视为“使用迭代器”,JVM 规范允许此优化) - 自定义类:需手动实现
Iterable,并返回一个合法的Iterator实例
迭代器的创建与生命周期
每次进入增强 for 循环,都会执行一次 iterable.iterator()。这意味着:
- 迭代器是**循环开始时一次性创建的**,不会重复创建(除非循环嵌套或多次执行该 for 语句)
- 如果在循环体中修改了原集合(如
list.remove(s)),大多数集合的迭代器会检测到并发修改,抛出ConcurrentModificationException(fail-fast 机制) - 迭代器的状态(如当前游标位置)完全独立于集合本身;多个增强 for 循环同时作用于同一集合,会各自拥有自己的迭代器实例
注意:不能在增强 for 中安全删除元素
下面写法是错误的:
for (String s : list) {
if ("abc".equals(s)) {
list.remove(s); // ❌ 可能触发 ConcurrentModificationException
}
}
正确方式是使用迭代器自身的 remove() 方法:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("abc".equals(s)) {
it.remove(); // ✅ 安全删除
}
}
增强 for 循环隐藏了迭代器变量,因此无法直接调用 it.remove() —— 这正是它“简化但受限”的体现。


















