增强for循环仅适用于Iterable集合或数组,语法为for (Type e : coll),不可修改集合结构,否则抛ConcurrentModificationException;需索引或删除时应选普通for或显式Iterator。

增强for循环的语法结构和适用范围
Java增强for循环(for-each)本质是编译器语法糖,底层仍调用Iterator或数组索引访问。它**只能用于实现了Iterable接口的集合类(如ArrayList、HashSet)或数组**,不能用于普通对象或未实现该接口的自定义容器。
基本写法:
for (Type element : collectionOrArray) { ... }
-
Type必须与集合/数组元素类型兼容,否则编译报错Incompatible types - 遍历过程中无法获取当前索引,也不能在循环体内修改集合结构(如
remove()),否则抛ConcurrentModificationException - 对数组使用时,不支持反向遍历或跳步,且无法区分是原始数组还是包装后的
List
常见错误:修改集合导致ConcurrentModificationException
增强for循环隐式使用迭代器,但不暴露Iterator.remove()方法。直接在循环中调用list.remove()或map.remove()会触发快速失败机制。
正确做法是改用显式Iterator:
立即学习“Java免费学习笔记(深入)”;
Iteratorit = list.iterator(); while (it.hasNext()) { String s = it.next(); if (s.startsWith("A")) { it.remove(); // 安全删除 } }
- 不要写
for (String s : list) { if (...) list.remove(s); }—— 这几乎必崩 - 若只需过滤,优先用
Collection.removeIf()(Java 8+):list.removeIf(s -> s.startsWith("A")) - 对
Map遍历时想删键值对,必须遍历entrySet()并用Iterator.remove(),不能遍历keySet()后调map.remove(key)
增强for vs 普通for:什么时候该选哪个
增强for简洁安全,但能力有限;普通for(含索引或Iterator)更灵活,代价是代码略长。
- 需要索引(如“第几个元素”“前后元素比较”)→ 必须用普通
for (int i = 0; i - 遍历
ArrayList且需随机访问 → 普通for性能略优(避免每次调iterator().next()) - 遍历
LinkedList或HashSet→ 增强for更合理(内部仍是迭代器,且避免了get(i)的O(n)开销) - 仅读取、无修改、无需索引 → 增强for语义清晰,首选
泛型擦除下容易忽略的类型陷阱
增强for的Type声明受泛型擦除影响,运行时无法校验。如果集合实际装了错误类型,会在循环体第一行赋值时抛ClassCastException。
ArrayList rawList = new ArrayList();
rawList.add("hello");
rawList.add(123);
// 编译通过,但运行时在第二次迭代时崩溃
for (String s : rawList) {
System.out.println(s.length()); // 第一次OK,第二次抛异常
}
- 永远用带泛型的集合声明:
ArrayListlist = new ArrayList(); - 避免混用原始类型(raw type)和泛型,尤其在跨模块传参时
- 若必须处理未知类型集合,增强for前先做
instanceof检查,或改用Object接收再转型









