4.3 while、for 与遍历
前置知识:布尔条件、作用域和赋值
预计时间:35 分钟
完成标志:能按条件、计数或元素遍历选择循环,并说明每一步顺序
while:先判断,再执行
int delivered = 0;
while (delivered < 10) {
delivered++;
System.out.println("交付第 " + delivered + " 块零件");
}每轮顺序:
判断条件
├─ false:结束循环
└─ true:执行循环体 → 回到条件循环正确性至少要回答:
- 初始状态是什么?
- 每轮如何推进?
- 终止条件何时变成
false? - 边界轮次是否多一次或少一次?
条件一开始就是 false 时,循环体一次也不执行。
for:把计数结构写在一处
for (int index = 0; index < 10; index++) {
System.out.println(index);
}执行顺序:
初始化(一次)
↓
条件
├─ false:结束
└─ true:循环体 → 更新 → 回到条件这解释了一个细节:在 for 中执行 continue 后,会先执行更新表达式,再检查条件;在 while 中,continue 直接回到条件,因此你必须确保状态已经推进。
for 的三部分都可以省略:
for (;;) {
// 显式无限循环
}无限循环本身不一定是错误。事件循环、服务器和消费者会长期运行,但必须设计取消、关闭、异常、退避和资源释放路径。教程练习通常使用最大轮数,避免失控。
半开区间减少边界错误
数组索引通常采用 [0, length):
int[] scores = {80, 90, 70};
for (int index = 0; index < scores.length; index++) {
System.out.println(index + ": " + scores[index]);
}初始索引包含 0,结束边界不包含 length。最后一个合法索引是 length - 1。
反向遍历:
for (int index = scores.length - 1; index >= 0; index--) {
System.out.println(scores[index]);
}空数组时初始值为 -1,条件立即为 false。
增强 for:按元素读取
for (int score : scores) {
System.out.println(score);
}适合不需要索引的遍历。循环变量接收每个元素值;给循环变量重新赋值不会改回基本类型数组:
for (int score : scores) {
score = 0;
}
System.out.println(scores[0]); // 仍是 80对对象数组,循环变量复制的是引用值;可以通过引用修改对象状态,但给循环变量指向另一个对象也不会替换数组元素。后续集合章节再讨论迭代期间结构修改。
do-while:先执行,再判断
int attempts = 0;
do {
attempts++;
System.out.println("attempt " + attempts);
} while (attempts < 1);循环体至少执行一次。末尾 while (...) 后必须有分号。它适合“先读取一次,再判断是否继续”的流程,但交互和资源代码还要处理输入结束、异常与取消。
不用浮点等值控制轮数
double value = 0.0;
while (value != 1.0) {
value += 0.1;
}二进制近似可能跳过精确的 1.0,使条件一直为 true。按次数迭代更可靠:
for (int step = 0; step < 10; step++) {
double value = step / 10.0;
System.out.println(value);
}若循环由物理误差阈值控制,应使用领域定义的容差并加入最大迭代次数,避免只靠一个近似条件保证终止。
常见循环错误
状态不推进:
int count = 0;
while (count < 10) {
System.out.println(count);
// 忘了更新 count
}分号形成空循环体:
for (int index = 0; index < 10; index++); // 空语句
{
System.out.println("只执行一次");
}格式化工具可能让结构更明显,但最终需要代码评审和测试覆盖 0 次、1 次、最后一次与超界条件。
Python 与 C++ 边界
Python for 遍历可迭代对象,range(10) 提供 0 到 9;它不是 C 风格三段式 for。Python 还支持循环 else:for 正常耗尽元素或 while 条件变为假时执行;break、return 或异常离开循环时不会执行。
C++ 有相似的 while、do-while、三段式和范围 for,但条件可发生到 bool 的上下文转换,类型、迭代器失效和未定义行为边界也不同,不能称为完全相同。
专业速查
| 情况 | 首选结构 |
|---|---|
| 已知计数或索引 | for |
| 由状态决定继续 | while |
| 至少执行一次 | do-while |
| 只读取每个元素 | 增强 for |
| 长期运行服务 | 明确取消、退避、异常和资源关闭 |
| 数值迭代 | 误差条件 + 最大迭代次数 |
离开这一页前
从空数组、单元素数组和三个元素的数组各走一遍 for,标出初始化、条件、循环体和更新发生的顺序。然后说明 continue 在 for 与 while 中分别落到哪里,以及为什么近似数值循环还需要最大迭代次数。能画出这几条路径,循环边界才算真正可检查。
下一页处理两种常见需求:找到目标后停止,遇到无效项时跳过本轮。