1. 概述
本文深入解析 Java 中的核心语法结构之一——for
循环。它是我们处理重复操作的利器,广泛应用于数组遍历、集合迭代、计数循环等场景。
掌握 for
的各种写法和适用场景,不仅能写出更简洁的代码,还能避免一些隐藏的“坑”。✅
2. 基础 for 循环
基础 for
循环是最经典的循环结构,通过初始化、条件判断和步进操作三部分控制循环执行。
其语法结构如下:
for (初始化; 布尔表达式; 步进操作)
语句;
来看一个最简单的例子:
for (int i = 0; i < 5; i++) {
System.out.println("Simple for loop: i = " + i);
}
输出:
Simple for loop: i = 0
Simple for loop: i = 1
Simple for loop: i = 2
Simple for loop: i = 3
Simple for loop: i = 4
⚠️ 注意:for
循环的三个部分(初始化、条件、步进)都是可选的。如果全部省略,就构成了一个无限循环:
for ( ; ; ) {
// 无限循环,等价于 while(true)
}
这种写法虽然少见,但在某些事件监听或守护线程中仍有使用场景,记得配合 break
使用,否则会一直跑下去 ❌。
2.1. 带标签的 for 循环
当遇到多层嵌套循环时,普通的 break
和 continue
只能作用于最内层循环,这时候就需要带标签的 for 循环来精准控制跳转。
看下面这个例子:
aa: for (int i = 1; i <= 3; i++) {
if (i == 1)
continue;
bb: for (int j = 1; j <= 3; j++) {
if (i == 2 && j == 2) {
break aa;
}
System.out.println(i + " " + j);
}
}
输出:
2 1
3 1
3 2
3 3
解释一下:
- 外层循环标记为
aa
,内层为bb
- 当
i=1
时,continue
跳过本次外层循环 - 当
i=2
且j=2
时,break aa
直接跳出整个外层循环,不再执行后续迭代
✅ 这种写法在处理复杂嵌套逻辑时非常有用,但也要注意别滥用,否则会影响代码可读性。
3. 增强 for 循环(for-each)
从 Java 5 开始引入的增强 for
循环(也叫 for-each),让遍历数组和集合变得简单粗暴。
语法如下:
for (元素类型 变量名 : 集合或数组)
语句;
它背后的核心思想是:
对
items
中的每个元素,将其赋值给item
变量,然后执行循环体。
来看个数组遍历的例子:
int[] intArr = { 0, 1, 2, 3, 4 };
for (int num : intArr) {
System.out.println("Enhanced for-each loop: i = " + num);
}
输出:
Enhanced for-each loop: i = 0
Enhanced for-each loop: i = 1
...
3.1. 遍历常见数据结构
增强 for
循环适用于所有实现了 Iterable
接口的类型,比如:
✅ List 遍历:
List<String> list = Arrays.asList("A", "B", "C");
for (String item : list) {
System.out.println(item);
}
✅ Set 遍历:
Set<String> set = new HashSet<>(Arrays.asList("X", "Y", "Z"));
for (String item : set) {
System.out.println(item);
}
✅ Map 遍历(通过 entrySet):
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Key: " + entry.getKey() + " - Value: " + entry.getValue());
}
⚠️ 注意:增强 for
循环虽然简洁,但有几点限制:
- 无法在遍历过程中修改集合(会抛
ConcurrentModificationException
) - 无法获取当前索引(除非自己维护计数器)
- 不适合需要反向遍历或跳跃访问的场景
3.2. Iterable.forEach() 与 Lambda
从 Java 8 开始,Iterable
接口新增了 forEach()
方法,结合 Lambda 表达式,让遍历更加函数式。
其默认实现如下:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
可以看到,它底层依然是基于增强 for
循环实现的。
使用示例:
List<String> names = new ArrayList<>();
names.add("Larry");
names.add("Steve");
names.add("James");
names.add("Conan");
names.add("Ellen");
names.forEach(name -> System.out.println(name));
输出:
Larry
Steve
James
Conan
Ellen
✅ 优点:
- 代码更简洁,语义更清晰
- 支持方法引用:
names.forEach(System.out::println);
- 更容易与 Stream API 集成
⚠️ 缺点:
- 调试不如传统循环直观
- 异常处理稍显麻烦(Lambda 中 checked exception 需要包装)
4. 总结
循环类型 | 适用场景 | 是否可修改集合 | 是否支持索引 |
---|---|---|---|
基础 for | 需要索引、反向遍历、复杂控制 | ✅ | ✅ |
增强 for (for-each) | 简单遍历数组/集合 | ❌ | ❌ |
Iterable.forEach | 函数式风格,结合 Lambda 使用 | ❌ | ❌ |
选择哪种 for
循环,关键看你的使用场景:
- 想快速打印集合?用
forEach()
✅ - 要边遍历边删元素?用
Iterator
❌(别用增强 for) - 需要精确控制循环变量?基础
for
最靠谱 ✅
所有示例代码已托管至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-lang-syntax