for-each循环适用于数组和iterable接口实现类;map需通过keyset()等方法间接遍历;编译后转为传统for或迭代器代码。
for-each 循环(增强型 for 循环)是 java 提供的语法糖,它让遍历数组和 iterable 实现类更简洁,但底层仍依赖传统 for 或迭代器。理解它怎么用、什么能用、以及编译后变成什么样,才能避免误用和排查隐含问题。
哪些类型能用 for-each?关键看是否“可迭代”
for-each 要求目标必须满足以下任一条件:
- 是数组(任意类型:基本类型数组、引用类型数组)
- 是实现了
java.lang.Iterable接口的类(如ArrayList、HashSet、LinkedList,或你自己写的类)
常见误区:Map 本身不实现 Iterable,所以不能直接 for (Entry e : map);但它的 keySet()、entrySet()、values() 返回值都实现了 Iterable,可以遍历。
实战写法与等效传统代码对照
✅ 正确示例及展开逻辑:
遍历数组:
int[] nums = {1, 2, 3};
for (int n : nums) {
System.out.println(n);
}
等价于:
int[] nums = {1, 2, 3};
for (int i = 0; i
<p><strong>遍历 ArrayList:</strong></p>
<pre class="brush:java;toolbar:false;">List<string> list = Arrays.asList("a", "b");
for (String s : list) {
System.out.println(s);
}</string>
等价于:
Iterator<string> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}</string>
⚠️ 注意:for-each 中无法获取索引、无法在遍历时安全删除元素(会抛 ConcurrentModificationException),需要这些操作请改用传统 for 或显式 Iterator.remove()。
字节码层面:它真不是新指令,只是编译器重写
用 javap -c 查看编译后的字节码,你会发现 for-each 完全消失,被替换为:
- 数组 → 普通计数循环(
iconst_0,iload,arraylength,iaload等) -
Iterable→ 调用iterator()+hasNext()+next()的标准迭代模式
例如遍历 ArrayList 时,字节码里一定包含对 iterator() 方法的 invokevirtual 调用,以及对 hasNext() 和 next() 的连续调用 —— 和你手写 Iterator 完全一致。它没有运行时开销优势,纯粹是语法简化。
自定义类支持 for-each:只需实现 Iterable
让你的类能用于 for-each,只需两步:
- 实现
Iterable<t></t>接口 - 重写
iterator()方法,返回一个能遍历内部数据的Iterator<t></t>
例如:
class Range implements Iterable<integer> {
private final int start, end;
Range(int start, int end) { this.start = start; this.end = end; }
public Iterator<integer> iterator() {
return new Iterator<integer>() {
private int current = start;
public boolean hasNext() { return current
<p>不复杂但容易忽略</p></integer></integer></integer>











