流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。
程序设计中规定的三种流程结构:
顺序结构
- 程序从上到下逐行地执行,中间没有任何判断和跳转。
分支结构
- 根据条件,选择性地执行某段代码。
- 有
if…else和switch-case两种分支语句。
循环结构
- 根据循环条件,重复性的执行某段代码。
- 有
for、while、do-while三种循环语句。 - 补充:JDK5.0 提供了
foreach循环,方便的遍历集合、数组元素。
一、顺序结构
顺序结构是所有流程控制语句结构中最基础的结构,顺序结构的程序从整体来看都是顺序执行的。
特点:上一行对某个变量的修改对下一行会产生影响。
示例代码:
public class Demo{
public static void main (String[] args){
int x = 1;
int y = 2;
System.out.println("x = "+ x);
System.out.println("y = "+ y);
//对x,y的值进行修改
x += 1;
y += x;
System.out.println("x = "+ x);
System.out.println("y = "+ y);
}
}
// 代码运行结果:
x = 1
y = 2
x = 2
y = 4
【注意】: 输出语句
- System.out.println("内容"); 语句在输出括号中的内容后会换行,即光标移动到下一行行首。
- System.out.print("内容"); 语句在输出括号中的内容后不换行,即光标还停留在内容后。
无论是哪一种输出语句,括号中都只能有一个值,要么是一个常量值,要么是一个变量值,要么是一个表达式的计算结果。如果有多个值,那么应使用运算符
+ 将它们连接起来。
二、分支结构
分支结构,是指程序中出现了多种选择,即某些语句可能执行,可能不执行,是否执行要看条件是否满足。
Java 主要提供两种分支结构:if 条件语句和 switch 选择语句。
1、if 条件语句
if 语句通过对条件表达式的求值结果(true 或 false)来决定执行哪个代码块。
根据程序路径的复杂性,if 语句可分为单分支、双分支和多分支三种形式。
注意:
条件表达式的结果只能是布尔类型,支持如下几种形式:
- 布尔型的变量。
- 布尔型的常量值。
- 布尔型的表达式,如关系表达式、逻辑表达式。
(1)单分支:if
当程序仅需在某个条件成立时执行特定操作时,使用单分支结构。
- 执行逻辑:如果条件表达式为
true,则执行其后的语句块;否则,跳过该语句块,继续执行后续代码,如图所示。

- 语法格式:
if(条件表达式){
语句块; ///如果条件表达式为true将执行的语句
}
(2)双分支:if...else
当程序需要在条件成立与不成立时,分别执行不同的操作(二选一)时,使用双分支结构。
- 执行逻辑:如果条件表达式为
true,执行if后的语句块;否则(为false),执行else后的语句块。

- 语法格式:
if(条件表达式) {
语句块1; //如果布尔表达式的值为true,执行语句块1
}else {
语句块2; //如果布尔表达式的值为false,执行语句块2
}
(3)多分支:if...else if...else
当程序需要在多个互斥的条件中选择一个来执行(多选一)时,使用多分支结构。
- 执行逻辑:程序从上至下依次判断每个
if或else if的条件表达式。一旦遇到第一个为true的条件,就执行其对应的语句块,然后跳出整个多分支结构。如果所有条件都不为true,则执行可选的else语句块。

- 语法格式:
if (条件表达式1) {
语句块1; //如果布尔表达式 1的值为true执行代码
} else if (条件表达式2) {
语句块2; //如果布尔表达式 2的值为true执行代码
}
...
}else if (条件表达式n) {
语句块n; //如果布尔表达式 n的值为true执行代码
} else {
语句块n+1; //如果以上布尔表达式都不为true执行代码
}
-
注意事项
- 可以有多个
else if 语句块。 - 单独的
else 语句块只能放在最后,不可以提到前面,根据实际情况,单独的 else 语句块是可选的。 -
else if 语句块中,else 关键字不可以省略,否则就不再是多分支。
- 可以有多个
-
特别注意
- 当多个条件是互斥(没有交集)关系时,多个条件的顺序可以随意执行,即执行它们的先后顺序不会影响结果;
- 当多个条件是包含(满足一个条件的情况完全包含在满足另一个条件的情况中,如 ≥90 分的成绩一定满足 ≥70 分)关系时,则按照"小上大下"或"子上父下"的条件编写,否则结果不同。
(4)嵌套
在 if 的语句块中,或者是在 else 语句块中,又包含了另外一个条件判断(可以是单分支、双分支、多分支),就构成了 嵌套结构。
-
执行特点:
- 如果是嵌套在 if 语句块中的,只有当外部的 if 条件满足,才会去判断内部的条件
- 如果是嵌套在 else 语句块中的,只有当外部的 if 条件不满足,进入 else 后,才会去判断内部的条件
-
注意 :
- 所有的流程控制语句都可以互相嵌套,互不影响
- 语句块只有一条执行语句时,一对
{}可以省略,但建议保留 - 当 if-else 结构是"多选一"时,最后的
else是可选的,根据需要可以省略 - 从开发经验上讲,没有超过三层的嵌套
(5)案例
需求:
求 ax2+bx+c=0 方程的解,其中 a、b、c 分别为方程的参数。
提示:
可以使用系统函数 Math.sqrt(x)求 x 的平方根。
案例分析:
-
如果 a≠0,那么该方程是一个一元二次方程,利用一元二次方程的判别式 Δ=,可以知道以下几点。
- 当 >0 时,一元二次方程有两个实数解:
- 当 =0 时,一元二次方程有两个相同的实数解:
- 当 <0 时,一元二次方程在实数范围内无解。
-
如果 a=0 且 b≠0,那么该方程是一个一元一次方程,方程的解为:
-
如果 a=0 且 b=0,那么提示参数输入有误,无法构成方程。
代码演示:

2、switch 选择语句
switch-case 是提供多分支程序结构语句。当多分支中的条件表达式是对同一个变量或表达式进行等值判断时,往往使用它代替实现。
(1)switch-case 基本语法与执行流程
-
执行逻辑:
switch首先计算括号内表达式的值,然后从上到下逐个与case后的常量值进行匹配。- 入口:一旦找到匹配的
case,程序就从该case处进入并执行其后的语句。如果所有case都不匹配,则从可选的default处进入。 - 出口:执行过程中遇到
break语句或整个switch结构的右大括号}时,执行结束。
- 入口:一旦找到匹配的

- 语法格式:
switch(变量或表达式){
case 常量值1:
语句块1;
//break;可选
case 常量值2:
语句块2;
//break;可选
... //可以有任意数量的case语句
default:
语句块n+1;
//break;可选
}
(2)注意事项
- 支持的类型:
switch表达式的类型支持byte,short,char,int。从 JDK 5.0 开始支持enum(枚举),从 JDK 7.0 开始支持String。 -
case 的要求:case后面必须跟一个常量值,不能是变量或表达式。且同一个switch块内,case的常量值必须唯一。 -
break 的作用:break用于强制跳出switch结构。 -
case 穿透:如果没有break,一旦匹配成功(表达式的值=常量值),则将贯穿执行下面的 case 或 default 中的语句,不再判断是否相等 。直到遇到 break 或者整个 switch 语句结束,执行终止。 这就是所谓的“穿透”。 -
default 子句:default是可选的,用于处理所有case都不匹配的情况。它的位置灵活,但无论放在哪里,都会在所有case匹配失败后才执行。习惯上将其放在末尾。
示例代码:
public class SwitchExample {
public static void main(String[] args) {
// 设置今天是星期四
int day = 4;
String dayString;
System.out.println("今天是星期 " + day + ",从今天开始到周末还有哪些活动:");
switch (day) {
case 1:
System.out.println("星期一: 开始新的工作周");
case 2:
System.out.println("星期二: 继续努力工作");
case 3:
System.out.println("星期三: 周中会议");
case 4:
System.out.println("星期四: 项目截止日期");
// 这里没有 break 语句
case 5:
System.out.println("星期五: 轻松一下,准备过周末");
// 这里没有 break 语句
case 6:
System.out.println("星期六: 外出游玩");
// 这里没有 break 语句
case 7:
System.out.println("星期日: 好好休息");
break; // 这个 break 会结束 switch 语句
default:
System.out.println("无效的日期");
break;
}
}
}
输出:
今天是星期 4,从今天开始到周末还有哪些活动:
星期四: 项目截止日期
星期五: 轻松一下,准备过周末
星期六: 外出游玩
星期日: 好好休息
(3)if-else 语句与 switch-case 语句比较
-
结论:
凡是使用 switch-case 的结构都可以转换为 if-else 结构。反之不成立。
-
开发经验:
如果既可以使用 switch-case,又可以使用 if-else,建议使用 switch-case。因为效率稍高。
-
细节对比:
| 特性 | if-else 语句 | switch 语句 |
|---|---|---|
| 判断条件 | 布尔表达式(true/false) | 同一个变量或表达式的等值判断 |
| 应用范围 | 更广。可用于范围判断(>, <, !=)和等值判断。 | 较窄。仅限于对 byte, short, char, int, enum, String 类型的等值判断。 |
| 性能 | 逐一判断,直到条件满足。 | 对于多分支且等值判断的场景,效率通常稍高。 |
| 特殊功能 | 无 | 可利用 case 穿透特性,执行多个分支。 |
三、循环结构
循环语句具有在 某些条件 满足的情况下,反复执行 特定代码的功能。
Java 提供了三种主要的循环语句,每种都有其最适用的场景。分别是 for、while 和 do-while
任何循环结构,无论是 for、while 还是 do-while,都由以下四个不可或缺的部分组成:
- 初始化表达式 (Initialization) :在循环开始前执行,通常用于声明和初始化循环控制变量。
- 循环条件 (Condition) :一个布尔表达式。每次循环迭代开始前都会进行求值,结果为
true 则执行循环体,为false 则终止循环。 - 循环体 (Body) :需要重复执行的代码块。
- 迭代表达式 (Iteration/Update) :在每次循环体执行完毕后执行,通常用于更新循环控制变量,使其向终止条件趋近。
1、while 循环:先判断,后执行
-
执行流程:
- 执行初始化表达式。
- 判断循环条件。
- 若条件为
true,执行循环体和迭代表达式。 - 返回步骤 2,重复此过程。
- 若条件为
false,跳出循环。

- 语法结构:
// ① 初始化部分
while (② 循环条件部分) {
// ③ 循环体部分;
// ④ 迭代部分;
}
// 执行顺序: ① -> ② (true) -> ③ -> ④ -> ② (true) -> ... -> ② (false) -> 结束
-
适用场景:适用于循环次数不确定,需要依赖某个条件来决定是否继续循环的场景。
-
案例:纸张折叠
- 需求:一张厚度为 0.1 毫米的纸,对折多少次后其厚度能超过珠穆朗玛峰的高度(8848.86 米)?
- 分析:这是一个典型的循环次数未知的场景,循环的终止条件是“纸张厚度 > 山峰高度”,因此使用
while 循环非常合适。 - 代码实现:
-
public class PaperFolding { public static void main(String[] args) { // 定义珠穆朗玛峰高度(单位:毫米) final double MOUNTAIN_HEIGHT_MM = 8848.86 * 1000; // 定义纸张初始厚度(单位:毫米) double paperThickness = 0.1; // 定义计数器,用于记录折叠次数 int foldCount = 0; // 循环条件:当前纸张厚度小于山峰高度 while (paperThickness < MOUNTAIN_HEIGHT_MM) { // 循环体:每次对折,厚度加倍 paperThickness *= 2; // 迭代:折叠次数加1 foldCount++; } System.out.println("需要对折 " + foldCount + " 次,才能超过珠穆朗玛峰的高度。"); } }
2、do-while 循环:先执行,后判断
do-while 循环是一种 “出口控制” 的循环结构。它保证循环体至少会被执行一次,然后再判断循环条件。
-
执行流程:
- 执行初始化表达式。
- 无条件地先执行一次循环体和迭代表达式。
- 判断循环条件。
- 若条件为
true,返回步骤 2,重复此过程。 - 若条件为
false,跳出循环。

- 语法结构:
// ① 初始化部分;
do {
// ③ 循环体部分;
// ④ 迭代部分;
} while (② 循环条件部分); // 注意:这里的分号(;)不能省略
// 执行顺序: ① -> ③ -> ④ -> ② (true) -> ③ -> ④ -> ... -> ② (false) -> 结束
-
适用场景:适用于那些无论条件如何,都至少需要执行一次循环体的业务逻辑,例如“先尝试,后判断”的场景。实际开发中较少使用。
-
案例:分期款款
- 需求:有一笔 100 元 的初始贷款。每年固定偿还 30 元。需要多少年才能还清全部贷款,并打印出每年的还款情况。
- 分析:无论贷款金额多少,都必须至少偿还一次。
- 代码实现:
-
public class LoanRepayment { public static void main(String[] args) { // 定义初始贷款金额 double loanAmount = 100.0; // 定义每年固定还款金额 final double REPAYMENT_PER_YEAR = 30.0; // 定义计数器,用于记录年份 int years = 0; System.out.println("贷款总额:" + loanAmount + "元,每年固定还款:" + REPAYMENT_PER_YEAR + "元。"); System.out.println("开始还款..."); // 使用do-while循环来模拟还款过程 do { // 循环体:至少会执行一次 // 1. 进行一次还款 loanAmount -= REPAYMENT_PER_YEAR; // 2. 年份计数器加1 years++; // 打印当年的还款状态 if (loanAmount > 0) { System.out.println("第 " + years + " 年后,剩余贷款:" + loanAmount + "元。"); } else { // 如果还款后余额小于等于0,说明已还清 System.out.println("第 " + years + " 年,贷款已还清!"); } } while (loanAmount > 0); // 循环条件:只要贷款余额大于0,就继续还款 System.out.println("\n最终,总共需要 " + years + " 年才能还清全部贷款。"); } } // 预期输出: 贷款总额:100.0元,每年固定还款:30.0元。 开始还款... 第 1 年后,剩余贷款:70.0元。 第 2 年后,剩余贷款:40.0元。 第 3 年后,剩余贷款:10.0元。 第 4 年,贷款已还清! 最终,总共需要 4 年才能还清全部贷款。
3、for 循环
循环结构最开始设计的是 while 结构,即强调循环条件成立就执行语句,直到循环条件不成立。
而引入 do...while 结构是为了满足至少执行一次循环体语句块的需求。
但在使用过程中,有一种情况很常见,那就是循环条件是一个区间值,从几循环到几,每次修改循环变量的迭代语句也很有规律,为了满足这种需求,从而设计了 for 循环结构。
for 循环是使用最广泛的循环结构。它将循环的四大核心要素(初始化、条件、迭代)集中写在了一起,结构清晰,特别适用于循环次数已知或有明确范围的遍历。
-
执行流程:
- 执行初始化表达式(仅一次)。
- 判断循环条件。
- 若条件为
true,执行循环体。 - 执行迭代表达式。
- 返回步骤 2,重复此过程。
- 若条件为
false,跳出循环。

- 语法结构:
for (① 初始化部分; ② 循环条件部分; ④ 迭代部分) {
// ③ 循环体部分;
}
// 执行顺序: ① -> ② (true) -> ③ -> ④ -> ② (true) -> ... -> ② (false) -> 结束zhu
-
注意:
- 两个分号必不可少,如果 for 括号中的三个表达式都省略,则相当于条件恒成立的
死循环。 - 循环变量初始化可以由多条变量初始化语句组成,中间用逗号隔开。循环变量更新也可以由多条更新语句组成,中间用逗号隔开。
- 两个分号必不可少,如果 for 括号中的三个表达式都省略,则相当于条件恒成立的
-
适用场景:数组遍历、固定次数的重复操作、按规律递增/递减的场景。
-
案例: 寻找水仙花数
- 需求:找出所有的三位数“水仙花数”(即该数等于其每位数字的立方和,如
153 = 1³ + 5³ + 3³)。 - 分析:遍历的范围是明确的(所有三位数,从 100 到 999),这是
for 循环的典型应用场景。 - 代码实现:
-
public class NarcissisticNumber { public static void main(String[] args) { System.out.println("所有的三位数水仙花数有:"); int count = 0; // 用于统计水仙花数的个数 // 循环遍历所有三位数 for (int num = 100; num < 1000; num++) { // 分解出个位、十位、百位 int ge = num % 10; int shi = num / 10 % 10; int bai = num / 100; // 判断是否满足水仙花数的条件 if ((ge * ge * ge + shi * shi * shi + bai * bai * bai) == num) { System.out.print(num + " "); count++; } } System.out.println("\n水仙花数共有 " + count + " 个。"); } }
- 需求:找出所有的三位数“水仙花数”(即该数等于其每位数字的立方和,如
4、三种循环语句的对比
| 特性 | for 循环 | while 循环 | do-while 循环 |
|---|---|---|---|
| 执行顺序 | 先判断,后执行 | 先判断,后执行 | 先执行,后判断 |
| 结构 | 四要素集中,结构紧凑 | 四要素分散,逻辑灵活 | 四要素分散,逻辑灵活 |
| 保证执行次数 | 可能 0 次 | 可能 0 次 | 至少 1 次 |
| 最佳适用场景 | 循环次数已知或有明确范围的遍历 | 循环次数未知,依赖条件判断 | 逻辑上要求循环体至少执行一次 |
相同点
- 都具备循环四要素,只是声明位置不同
- 本质上三种循环之间完全可以互相转换,都能实现循环的功能
不同点
- 语法不同

-
执行循序不同
-
while 和for 语句:先判断后执行。 -
do…while 语句:先执行后判断(至少执行一次循环体语句)
-
选择策略
- 首选
for 循环:当遍历有明确的起止点或次数时(如遍历数组、集合),for 循环是代码最清晰、最符合编程习惯的选择。 - 次选
while 循环:当循环的持续依赖于一个运行时才能确定的条件时(如读取文件直到末尾、等待用户输入特定指令),while 更为合适。 - 慎用
do-while 循环:仅在业务逻辑明确要求“先执行一次再判断”的罕见场景下使用。在多数情况下,其逻辑可被while 替代,因此使用频率最低。
5、嵌套循环
一个循环的循环体内包含另一个完整的循环结构,称为嵌套循环。
- 执行特点:外层循环每执行一次,内层循环都要完整地执行一轮(从开始到结束)。
- 执行总次数:若外层循环执行 M 次,内层循环执行 N 次,则内层循环体总共会执行
M * N 次。 - 开发技巧:在处理二维数据或打印二维图形时,通常将外层循环看作控制行,内层循环看作控制列。
案例:打印九九乘法表

public class MultiplicationTable {
public static void main(String[] args) {
// 外层循环控制行数 (从1到9)
for (int i = 1; i <= 9; i++) {
// 内层循环控制列数 (列数不超过当前行数)
for (int j = 1; j <= i; j++) {
System.out.print(j + " * " + i + " = " + (i * j) + "\t");
}
// 每打印完一行后,换行
System.out.println();
}
}
}
6、跳转语句
跳转语句就是在中途改变程序原本的执行过程的语句,由 break 或 continue 关键字修饰。
break 的意思为中断,用于 switch-case 或循环结构中,表示提前结束 switch 或当前循环。
continue 的意思为继续,只能用于循环结构中,表示继续下一次循环,本次循环剩下的循环体语句将被跳过。
| 关键字 | 使用范围 | 作用 |
|---|---|---|
break | switch 或循环结构 | 立即终止并跳出当前所在的整层循环或 switch。 |
continue | 循环结构 | 立即结束本次循环迭代,跳过循环体中余下的语句,直接开始下一次迭代。 |
- 相同点:
break或continue的后面不能声明执行语句。 - 核心区别:
break 是“不玩了,直接结束”,而continue 是“这次算了,继续下次”。 - 注意:在嵌套循环中,
break 和continue 默认只对最内层的循环起作用。如果想控制外层循环,需要使用“标签(label)”,但应谨慎使用以避免代码逻辑复杂化。 - 开发中,break 的使用频率要远高于 continue。
案例:
public class JumpStatementsDemo {
public static void main(String[] args) {
// 示例1:在循环中使用break
// 当数字等于5时,中断整个循环
System.out.println("使用 break 结束整个循环:");
for (int i = 1; i <= 10; i++) {
if (i == 5) {
// 当 i 等于 5 时,使用 break 退出整个循环,
// 后续循环中的代码不会执行
break;
}
System.out.println("数字:" + i);
}
/*
结果:
使用 break 结束整个循环:
数字:1
数字:2
数字:3
数字:4
*/
// 示例2:在循环中使用continue
// 当数字等于5时,跳过当前循环剩下的部分,直接进入下一次循环
System.out.println("使用 continue 跳过当前循环的剩余部分:");
for (int i = 1; i <= 10; i++) {
if (i == 5) {
// 当 i 等于 5 时,使用 continue 跳过本次循环中后续代码
// 但循环会继续进行下一次迭代
continue;
}
System.out.println("数字:" + i);
}
/*
结果:
使用 continue 跳过当前循环的剩余部分:
数字:1
数字:2
数字:3
数字:4
数字:6
数字:7
数字:8
数字:9
数字:10
*/
}
}
四、本章小结
本章学习了流程控制结构:顺序结构、分支结构、循环结构。
实际上,一个完整的程序中这几种结构往往是密不可分的。
顺序结构区别于其他两种结构,顺序结构是伴随所有的 Java 程序存在的,在 Java 的编程体系中,默认的结构就是顺序结构,是自上而下的设计。
分支结构是有选择的语言控制,Java 中的分支结构包含两组关键字:if 和 switch。其中 if 包含三种结构:单分支结构、双分支结构和多分支结构,单分支结构和双分支结构的应用场景少一些。一旦涉及太多的选择,就需要使用多分支结构,但是多分支结构操作起来太过烦琐,不如 switch 结构简单明了,当然前提是 switch 结构能解决多分支的需求问题。
循环结构主要有三组关键字:do…while、for、while。
do...while 实现的是先执行循环体和迭代表达式后判断的循环。
while 在执行前先判断条件是否成立再执行循环体语句。
for 和 while 一样是先判断条件是否成立再执行循环体语句,但是 for 的使用更加简洁。
除以上三种循环结构,还有多重循环嵌套,也就是三种循环结构结合在一起使用。由于多重嵌套循环直接影响程序运行效率,所以在程序开发中不到万不得已的情况下,尽量避免使用嵌套循环。