Java 循环与流程控制
这是 Java 入门系列的第四天。顺序结构让程序从上往下走,选择结构让程序拐弯,今天要学的循环结构则让程序”重复”——这是计算机最擅长的事:不知疲倦地把一件事做一万次。
本篇目标
- 掌握 for、while、do-while 的语义差异与选型原则
- 理解嵌套循环”外行内列”的模型,能打印常见图案
- 说清 break、continue、return 的真实语义和标号的用法
- 完成两个经典练习:九九乘法表与素数判断
for:次数已知时的首选
for (int i = 1; i <= 10; i++) { |
执行顺序是四步循环:初始化(只执行一次)→ 判断条件(false 则结束)→ 执行循环体 → 执行迭代语句 → 回到判断。三个表达式把”从哪开始、到哪结束、每次怎么走”写在同一行,结构一目了然——这正是次数已知时优先用 for 的原因。
两个基础练习背后是两种重要的思想模式:
累加思想:求 1~100 的和,套路是”循环外定义累加器,循环内累加”。
int sum = 0; |
统计思想:统计满足条件的个数,套路是”循环外定义计数器,循环内判断后自增”。
int count = 0; |
累加器和计数器是后面一切数据处理(求平均分、统计及格人数)的原型,务必练熟。
顺带提醒一个经典笔误:for (int i = 0; i < 10; i++);——括号后多写一个分号,循环体就变成了空语句,后面的大括号块只会执行一次。”有左大括号就没有分号,有分号就没有左大括号”,这句话值得记住。
while:条件驱动
int i = 1; // 初始化 |
while 与 for 本质上等价(for 的三个部分拆开就是 while),差异在变量作用域与语义:for 的循环变量属于 for 内部,循环结束即销毁,省内存;while 的变量定义在循环外,循环结束后还能继续使用。语义上,while 表达的是”只要条件成立就一直做”,至于做多少次事先并不知道——比如”不断读取用户输入,直到输入 quit”。这种次数未知的场景,用 while 比 for 自然。
do-while:至少执行一次
do { |
它先执行循环体再判断条件,因此无论条件真假,循环体至少执行一次。适合”必须先做一遍再决定要不要继续”的场景,比如先打印一次菜单再等用户选择。使用频率远低于前两者,但语义必须清楚。
| 循环 | 判断时机 | 最少执行次数 | 典型场景 |
|---|---|---|---|
| for | 先判断 | 0 | 次数已知 |
| while | 先判断 | 0 | 次数未知、条件驱动 |
| do-while | 后判断 | 1 | 至少要做一次 |
死循环不是洪水猛兽
while (true) {} 与 for (;;) {} 是两种标准的死循环写法。它们并非总是 bug——服务器的主循环、游戏的渲染循环、命令行程序的”打印菜单 → 读输入 → 处理”循环,本质上都是刻意为之的死循环,配合 break 退出。真正要避免的是意外死循环:循环变量忘了更新、更新方向写反,程序就卡死了。
嵌套循环:外行内列
打印一个 4 行 5 列的星号矩阵:
for (int i = 0; i < 4; i++) { // 外循环:行 |
核心模型就一句话:外循环控制行数,内循环控制列数。让内循环的上限跟着外循环变量走,图案就活了——比如打印直角三角形:
for (int i = 1; i <= 5; i++) { |
实战一:九九乘法表
public class MultiplicationTable { |
"\t" 是制表符,把每个算式对齐到下一个制表位,输出就是整齐的三角阵。常见的转义字符还有 \n 换行、\r 回车、\" 双引号本身。
break、continue、return 与标号
三个跳转语句经常被混为一谈,其实层次完全不同:
- break:跳出当前一层循环(或 switch),循环整体结束。
- continue:跳过本次循环体的剩余部分,直接进入下一次迭代——循环并没有结束。
- return:结束的是整个方法,循环只是顺带被终结,方法内后面的代码都不会执行。
嵌套循环里 break 只能跳一层,想直接跳出外层循环需要标号:
outer: |
标号就是一个合法标识符加冒号。日常代码更推荐通过抽取方法来避免标号(return 天然能跳多层),但读老代码时要认得它。
练习:推理 break 与 continue 的输出
看一道经典填空题,检验是否真的理解了二者的差异:
for (int x = 1; x <= 10; x++) { |
- 想输出 2 次:填
break;。x = 3 时满足条件直接跳出循环,只有 x = 1、2 两次打印。 - 想输出 7 次:填
continue;。x = 3、6、9 三次被跳过,10 - 3 = 7 次打印。 - 想输出 13 次:在 if 里加一句
System.out.println("Java");。正常打印 10 次,x = 3、6、9 时各多打一次,共 13 次。
把这道题想透,break”终结循环”和 continue”跳过本次”的区别就再也不会混了。
实战二:素数判断
素数是只能被 1 和自身整除的大于 1 的整数。朴素写法是试遍 2 到 n-1,但有个重要的优化:
public class PrimeDemo { |
为什么试到 √n 就够了?因为因子是成对出现的:若 n = a × b 且 a ≤ b,那么必有 a ≤ √n。如果 √n 以内都找不到因子,更大的一侧也不可能单独存在。这个优化把循环次数从 n 降到 √n——n 是一百万时,从约一百万次降到一千次,这就是算法思想的力量。
在单数判断外面再套一层循环,就得到 1~100 的全部素数:
public class PrimeList { |
“内层解决一个问题,外层批量重复”——这是嵌套循环最典型的用法,和打印图案是同一个思维模式。
小结
- 次数已知用 for,条件驱动用 while,至少执行一次才考虑 do-while。
- 累加器与计数器是循环处理的两大基本模式。
- 嵌套循环记牢”外行内列”;内层上限依赖外层变量,就能打印三角形和九九乘法表。
- break 跳本层、continue 跳本次、return 结束方法;跨层跳转用标号,但更推荐抽方法。
- 素数判断试到 √n 即可,找到因子立刻 break,别做无用功。

