6.Java流程控制之循环结构:让程序“跑起来“
2026/8/24 14:12:11 网站建设 项目流程

开篇:为什么需要循环?

上篇我们学会了 if/switch,让程序具备了"做决定"的能力。但现实中还有一类任务非常枯燥却必不可少——重复执行同一段代码。

想象一下:让你把"我爱Java"打印 100 遍,难道要手写 100 行 System.out.println?计算 1 到 100 的和,难道要 1+2+3+…+100 一行行加?让用户反复输入密码直到正确,难道要 if 套 if 套 if?

这时候就需要循环结构登场了。循环让一段代码按规则反复执行,直到满足退出条件为止。Java 提供了 3 种循环:for、while、do-while,外加一个遍历数组/集合用的"语法糖"——增强 for (for-each)。本文一次讲透,配套大量案例和避坑。

💡本篇导读
本文带你掌握:① for 循环(最常用);② while 循环;③ do-while 循环;④ break 与 continue 的区别;⑤ 嵌套循环(九九乘法表);⑥ 死循环的正确用法;⑦ 增强 for-each 初体验;⑧ 10 个高频避坑 + 4 道动手练习。

一、for 循环:已知次数时的首选

for 是开发中用得最多的循环结构,特点是把"初始化、条件判断、迭代更新"三要素写在同一行,结构紧凑、不易遗漏,特别适合已知循环次数的场景。

1.1 基本语法

for(初始化语句;条件判断;迭代更新){// 循环体:要重复执行的代码}

三个位置的含义:

位置作用执行时机典型写法
初始化语句定义/声明循环变量循环开始前执行 1 次int i = 1
条件判断决定是否继续循环每次循环开始前判断i <= 100
迭代更新修改循环变量每次循环体结束后执行i++ / i–

执行顺序是:初始化 → 判断条件 → true 则执行循环体 → 迭代更新 → 再判断条件 → …… → false 时退出。

1.2 入门案例:打印 1~5 与 5~1

// 从小到大输出 1 2 3 4 5for(inti=1;i<=5;i++){System.out.println(i);}// 从大到小输出 5 4 3 2 1for(inti=5;i>=1;i--){System.out.println(i);}

1.3 案例:求 1~100 的和(累加器模式)

循环最经典的用法就是"累加"。记住一个固定套路:先准备一个累加器变量 sum = 0,循环里不断 sum += 变量。

intsum=0;// 累加器,初始为0for(inti=1;i<=100;i++){sum+=i;// 等价于 sum = sum + i;}System.out.println("1~100的和是:"+sum);// 输出 5050

💡套路总结
以后题目里出现 “求和”、“统计个数”、“累加”、“累计” 这类字眼,脑子里立刻跳出:准备一个变量初始化为0 → 循环中不断 += 或 ++。求偶数和就在循环体里加个 if(i % 2 == 0) 判断即可。

1.4 案例:求所有三位"水仙花数"

水仙花数:一个三位数,其个位³ + 十位³ + 百位³ = 它本身,如 153 = 1³+5³+3³ = 1+125+27 = 153。思路:循环 100~999,逐位拆分判断。

for(inti=100;i<=999;i++){intge=i%10;// 个位intshi=i/10%10;// 十位intbai=i/100;// 百位if(ge*ge*ge+shi*shi*shi+bai*bai*bai==i){System.out.println(i);// 153 370 371 407}}

一共 4 个水仙花数:153 / 370 / 371 / 407,这个题目是面试/考试常客,务必敲一遍。

1.5 for 的灵活写法

for 三个表达式都可以省略(但两个分号不能省):

// ① 省略初始化:变量在外面声明inti=1;for(;i<=5;i++){...}// ② 省略条件判断:相当于永远true,成了死循环for(inti=1;;i++){if(i>5)break;// 循环体里自己跳出去...}// ③ 省略迭代更新:在循环体里自己改for(inti=1;i<=5;){...i++;}// 极端情况:三个都省略——经典死循环for(;;){...}

⚠️初学者别这么省
省略写法是语法允许,但日常开发强烈建议把三要素写完整。省略后可读性明显下降,而且很容易漏掉更新语句导致死循环。

二、while 循环:不知道次数时用它

while 循环是"当型循环"——先判断,再执行。适合不知道具体循环多少次,只知道"当某个条件满足时一直做"的场景。

2.1 基本语法

初始化语句;while(条件判断){// 循环体// 迭代更新(别漏了!)}

注意:while 的初始化语句写在循环外面,迭代更新要自己写在循环体里。

2.2 for 和 while 可以互相改写

// for 版本for(inti=1;i<=5;i++){System.out.println(i);}// while 版本(等价)inti=1;while(i<=5){System.out.println(i);i++;}

2.3 经典案例:纸张折叠超珠峰

珠峰高 8844430 毫米,一张纸厚 0.1 毫米,折叠多少次能超过珠峰?——次数未知,用 while 最合适。

doublepaper=0.1;// 纸张厚度(毫米)intzf=8844430;// 珠峰高度intcount=0;// 折叠次数while(paper<=zf){paper*=2;// 折叠一次厚度翻倍count++;}System.out.println("需要折叠"+count+"次");// 27次System.out.println("最终厚度:"+paper);// 约1342万毫米

答案是 27 次,每次翻倍确实夸张,这就是指数增长的力量。

⚠️while 小括号后千万别加分号!
写 while (i <= 5); { … } 会让分号成为空循环体,真正的大括号与 while 无关,要么死循环,要么逻辑错乱。写完 while 条件直接写大括号,别手抖按分号。

三、do-while 循环:至少执行一次

do-while 是"直到型循环"——先执行一次循环体,再判断条件。也就是说无论条件成立与否,循环体至少执行 1 次。

3.1 基本语法

初始化语句;do{// 循环体// 迭代更新}while(条件判断);// ← 这里末尾有分号!

⚠️do-while 末尾必须加分号!
这是和 while 的一个关键区别:while(…) { } 后面不加分号;do { } while(…); 后面必须加分号。记混了就是编译错误。

3.2 案例体验:先斩后奏

inti=11;do{System.out.println("Hello");// 仍然会输出一次i++;}while(i<=10);// 条件一开始就是 falseSystem.out.println("i="+i);// i=12

虽然初始 i=11 已经不满足 i<=10,但 “Hello” 还是被打印了一次——这就是 do-while 的"先执行后判断"特点。

3.3 典型使用场景:用户输入校验

比如"让用户反复输入密码,直到正确为止":至少要让用户输一次,用 do-while 语义最贴切。

Scannersc=newScanner(System.in);intpwd;do{System.out.print("请输入密码:");pwd=sc.nextInt();}while(pwd!=123456);System.out.println("登录成功!");

四、三种循环怎么选?

对比项forwhiledo-while
执行顺序先判后执行先判后执行先执行后判断
循环次数已知时首选未知条件首选至少执行1次
初始化位置for括号内循环外循环外
迭代更新括号内第三处循环体内自写循环体内自写
分号问题括号后别加分号末尾必须加分号
使用频率★★★★★★★★★☆★☆☆☆☆

一句话记忆:次数确定用 for,次数不确定用 while,至少执行一次用 do-while。实际开发中 for 和 while 占 95% 以上,do-while 偶尔用。

五、循环控制:break 与 continue

有时我们不想等循环自然结束,而是想中途跳出或跳过某一次,这就需要两个"跳转"关键字。

5.1 break:立刻跳出本层循环

break 的作用是立即终止并跳出当前所在的循环(或 switch),后面的循环次数全部不再执行。

// 找到第一个能被7整除的三位数就停下for(inti=100;i<=999;i++){if(i%7==0){System.out.println("找到:"+i);// 105break;// 直接跳出for}}// break 之后直接到这里

5.2 continue:跳过本次,进入下一次

continue 的作用是跳过本次循环剩余的语句,直接进入下一次循环的条件判断。注意它不终止整个循环,只是"这轮我不玩了"。

// 打印1~10,但跳过3的倍数for(inti=1;i<=10;i++){if(i%3==0){continue;// 跳过后面的打印,直接i++进下一轮}System.out.println(i);// 1 2 4 5 7 8 10}

5.3 对比表

关键字作用类比理解
break跳出整个循环(或switch)辞职不干了,直接走人
continue跳过本次,继续下一次今天请假,明天继续上班

💡带标签的 break/continue(了解即可)
Java 支持给循环起标签名,可以一次性跳出多层嵌套循环。例如 outer: for(…) { for(…) { break outer; } } 可以直接从内层跳出外层。初学者暂时不用掌握,先把单层 break/continue 用熟。

六、嵌套循环:循环里套循环

循环体里还能再写循环,这叫循环嵌套。最经典的例子就是九九乘法表——外层控制"第几行",内层控制"这行打几列"。

6.1 经典案例:九九乘法表

for(inti=1;i<=9;i++){// 外层:行数 1~9for(intj=1;j<=i;j++){// 内层:列数 1~iSystem.out.print(j+"*"+i+"="+(i*j)+"\t");}System.out.println();// 一行打完换行}

输出效果(示意):

1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 ... 1*9=9 2*9=18 ... 9*9=81

💡嵌套循环怎么看?
记住一个诀窍:外层循环走1次,内层循环走完整轮。外层 i=1 时内层 j 循环 1 次;外层 i=2 时内层 j 循环 2 次……以此类推。多层嵌套同理,但日常开发一般不超过 3 层,否则性能和可读性都灾难。

6.2 案例:打印矩形/三角形

// 打印 5行5列 星号矩形for(inti=1;i<=5;i++){for(intj=1;j<=5;j++){System.out.print("* ");}System.out.println();}// 打印直角三角形for(inti=1;i<=5;i++){for(intj=1;j<=i;j++){System.out.print("* ");}System.out.println();}

七、死循环:是 Bug 也是武器

如果循环条件永远为 true、或者忘记写迭代更新,循环就永远停不下来——这就是死循环。

7.1 死循环是怎么造成的?

// ❌ 漏写迭代更新inti=1;while(i<=5){System.out.println(i);// i++ 被吃掉了!i 永远是1,条件永远true}// ❌ for 的迭代更新写错for(inti=1;i<=5;i--){// i 越变越小,永远到不了5System.out.println(i);}

7.2 故意写死循环:服务器/菜单场景

死循环不一定是 Bug!很多场景下我们故意写死循环,然后在循环体内部控制退出。比如:

// 服务器主循环:一直等待用户请求while(true){// 接收请求、处理、响应if(收到退出指令)break;}// 菜单选择Scannersc=newScanner(System.in);while(true){System.out.println("1.查询 2.存款 3.取款 0.退出");intchoice=sc.nextInt();if(choice==0){System.out.println("再见!");break;}// 根据 choice 做相应处理...}

while(true) 和 for(;😉 是两种最常见的故意死循环写法,效果完全一样。

八、增强 for 循环(for-each):遍历神器

从 JDK 5 开始,Java 提供了一种专门用来遍历数组或集合的简化写法——增强 for 循环,也叫 for-each。它隐藏了索引,代码更简洁。

数组我们还没正式讲(下一篇会讲),这里先给你看一眼"长相",有个印象:

8.1 基本语法

for(元素类型 变量名:数组或集合){// 直接用"变量名"代表当前元素}

8.2 对比示例

int[]nums={10,20,30,40,50};// 普通for:要自己管索引 ifor(inti=0;i<nums.length;i++){System.out.println(nums[i]);}// 增强for:直接拿元素,不需要索引for(intnum:nums){System.out.println(num);}

8.3 优点和局限

维度增强 for 特点
优点语法简洁,不会数组越界,可读性好
局限1拿不到当前元素的索引
局限2遍历过程中不能删除/添加集合元素(会抛异常)
局限3不能反向遍历、不能跳步
适合场景只想"把所有元素读一遍",不需要索引和修改

初学阶段你先记住:只要是"从头到尾遍历一遍、只读不改",增强 for 最省事;需要索引或修改元素时,用回普通 for。

九、避坑总结:10 条血泪教训

#坑点正确做法
1for 括号内三个表达式用逗号而非分号分隔用两个分号 ; 分隔三部分
2for/while 循环体漏写迭代更新(死循环)确保每次循环都能让条件趋向 false
3while(…) 后误写分号,大括号变独立块条件后直接跟 {,不要加分号
4do-while 末尾漏写分号} while(条件); 末尾必须有 ;
5循环变量作用域搞错(for内声明的外部不能用)需要外部访问时把变量声明提到 for 外
6break/continue 混淆:break是走人,continue是请假牢记对比表,写前想清楚意图
7嵌套循环 break 只跳出本层要跳多层用带标签的 break
8浮点数做循环变量精度丢失循环变量尽量用 int 整数
9在增强for中删除/添加集合元素要用 Iterator 或普通 for 倒序删
10循环内声明变量导致每次重新创建(性能)能提出来的对象尽量提到循环外

⚠️重点强调:浮点数不要做循环变量
看这段代码你猜输出什么?

for(doublex=0;x!=1.0;x+=0.1){System.out.println(x);}

答案是:死循环!因为 0.1 在二进制中是无限循环小数,累加多次后会产生精度误差,x 永远不可能精确等于 1.0。循环变量请始终使用 int 等整数类型。

十、实战案例:3 个小练习

案例1:猜数字游戏

系统随机生成 1~100 的整数,用户反复猜,直到猜对为止,每次提示"大了"或"小了"。

Scannersc=newScanner(System.in);inttarget=(int)(Math.random()*100)+1;// 1~100随机数intguess;intcount=0;do{System.out.print("猜一个1~100的数:");guess=sc.nextInt();count++;if(guess>target)System.out.println("大了");elseif(guess<target)System.out.println("小了");elseSystem.out.println("猜对了!共猜了"+count+"次");}while(guess!=target);

案例2:求 1~100 内能被 3 整除但不能被 5 整除的数的个数

intcount=0;for(inti=1;i<=100;i++){if(i%3==0&&i%5!=0){count++;}}System.out.println("共"+count+"个");// 27

案例3:判断一个数是不是质数(素数)

质数:大于 1 的自然数,除了 1 和它本身,不能被其他数整除。思路:从 2 到 sqrt(n) 试除,只要能整除就不是质数。

intn=97;booleanisPrime=true;for(inti=2;i<=Math.sqrt(n);i++){if(n%i==0){isPrime=false;break;// 已经找到因子,不用再判了}}System.out.println(isPrime?"是质数":"不是质数");

十一、动手练习(先自己写再对答案)

练习1:求阶乘

输入一个正整数 n(n≤12),求 n! = 1×2×3×…×n。比如 5! = 120。提示:准备一个乘积变量,初始值为 1(不能为0!),循环里用 *= 累乘。

练习2:打印倒三角形

在控制台输出如下图案(5行星号倒三角):

* * * * * * * * * * * * * * *

练习3:百元买百鸡

公鸡5文一只,母鸡3文一只,小鸡1文3只。用100文买100只鸡,问公鸡、母鸡、小鸡各多少只?提示:双层 for 循环暴力枚举,第三只鸡用 100-i-j 计算,然后验证钱数。

练习4:斐波那契数列

兔子繁殖问题:第1、2项都是1,之后每项等于前两项之和(1,1,2,3,5,8,13…)。请打印前20项。

💡下篇预告 🚀
学会了循环,你已经能写出"会动的程序"了。但目前我们手里还都是"单个数据",处理 100 个学生成绩难道要声明 100 个变量?下一篇我们将学习 Java 里最重要的数据容器——数组:一维数组、二维数组、Arrays工具类、常见排序查找算法,让你的程序能批量处理数据。

— 本文完 —

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询