4. 流程控制语句:if-else、switch、for、while、do-while循环、break与continue的使用
流程控制语句是Java程序实现逻辑判断与重复操作的核心语法机制。在《计算机二级Java程序设计》考试中,流程控制不仅涉及语法正确性,更考查逻辑组织能力与边界条件处理。本章将系统讲解选择结构(if-else、switch)与循环结构(for、while、do-while)的语法规则、执行流程、适用场景,以及break与continue对循环行为的干预方式。掌握这些语句的本质区别与嵌套技巧,是编写健壮、高效Java程序的基础。
4.1 选择结构:if-else与switch
4.1.1 核心原理
选择结构根据条件表达式的布尔结果决定程序执行路径。if-else语句适用于区间判断、复合逻辑(与或非)以及需要灵活条件组合的场景;switch语句则专用于等值匹配,其底层使用跳转表实现,在分支较多且判断值为离散常量时执行效率更高。Java 7之后switch支持String类型,Java 14起引入switch表达式(箭头语法),但二级考试仍以经典switch语句为主。
4.1.2 语法与判断方法
// if-else 三种形式
if (条件) { /* 条件为true时执行 */ }
if (条件) { /* true分支 */ } else { /* false分支 */ }
if (条件1) { /* 分支1 */ }
else if (条件2) { /* 分支2 */ }
else { /* 兜底分支 */ }
// switch 经典语法
switch (表达式) {
case 值1: 语句; break;
case 值2: 语句; break;
default: 语句; break; // 可选
}
判断方法要点:
- if-else选择依据:条件表达式必须是boolean类型,不能直接写数字(如
if(1)错误);else if按顺序从上到下匹配,一旦命中即跳出整个if-else链。 - switch选择依据:表达式类型限byte/short/int/char/String/枚举;case值必须是编译期常量,且不能重复;省略break会产生case穿透,即继续执行后续case直到遇到break或switch结束。
- 嵌套注意:else总是与最近的未配对if结合(悬空else问题),建议使用大括号明确层级。
4.1.3 案例拆解:成绩等级评定
某高校成绩评定规则:90-100为A,80-89为B,70-79为C,60-69为D,60以下为E。要求输入成绩(0-100整数),输出对应等级。
int score = 85;
// 方案一:if-else if 链(适合区间判断)
if (score >= 90) {
System.out.println("A");
} else if (score >= 80) {
System.out.println("B");
} else if (score >= 70) {
System.out.println("C");
} else if (score >= 60) {
System.out.println("D");
} else {
System.out.println("E");
}
// 方案二:switch(需先转换为等级段)
int level = score / 10; // 整除取十位
switch (level) {
case 10:
case 9: System.out.println("A"); break;
case 8: System.out.println("B"); break;
case 7: System.out.println("C"); break;
case 6: System.out.println("D"); break;
default: System.out.println("E"); break;
}
案例复盘:方案一逻辑直观,适合区间判断;方案二利用整除将连续区间映射为离散值,利用case穿透合并10和9两个分支,代码更紧凑。实际开发中,若判断条件为区间,优先if-else;若为固定离散值(如菜单选项、状态码),优先switch。注意方案二未处理score超出0-100的异常输入,生产环境需增加合法性校验。
=而非等值判断==,导致条件恒为true;② switch中遗漏break造成意外穿透;③ case值使用变量(非常量)导致编译错误;④ 浮点数直接比较相等(如if (x == 0.1))因精度问题可能判断失败。
4.2 循环结构:for、while与do-while
4.2.1 核心原理
循环结构用于重复执行一段代码块,直到循环条件不再满足。for循环将初始化、条件判断、迭代更新集中在头部,适合已知循环次数的场景;while循环先判断条件再执行,适合循环次数未知但终止条件明确的场景;do-while循环先执行一次再判断,保证循环体至少执行一次,适合“至少需要执行一次”的业务逻辑(如菜单显示、用户输入校验)。
4.2.2 语法对比与选择方法
| 循环类型 | 语法结构 | 执行次数 | 适用场景 |
|---|---|---|---|
| for | for(初始化; 条件; 迭代){ } |
0~N次(条件初始为false则0次) | 遍历数组/集合、固定次数计数 |
| while | while(条件){ } |
0~N次(先判断) | 读取文件直到EOF、等待用户输入特定值 |
| do-while | do{ }while(条件); |
至少1次 | 菜单循环显示、先执行后验证 |
选择判断流程:
- 若循环次数由计数器或数组长度明确决定,选择for循环。
- 若循环次数未知,但存在明确的终止条件(如输入特定字符退出),选择while循环。
- 若循环体必须至少执行一次(如先显示菜单再询问用户是否继续),选择do-while循环。
4.2.3 案例拆解:数字累加与死循环排查
场景:计算1到100之间所有偶数的和,并输出结果。要求分别用三种循环实现,并分析各自的边界处理。
// for实现
int sumFor = 0;
for (int i = 2; i <= 100; i += 2) {
sumFor += i;
}
System.out.println("for结果: " + sumFor);
// while实现
int sumWhile = 0;
int j = 2;
while (j <= 100) {
sumWhile += j;
j += 2;
}
System.out.println("while结果: " + sumWhile);
// do-while实现
int sumDo = 0;
int k = 2;
do {
sumDo += k;
k += 2;
} while (k <= 100);
System.out.println("do-while结果: " + sumDo);
分析过程:三种循环均从2开始,步长为2,终止条件为i <= 100。for循环将迭代变量i的作用域限制在循环内部,避免外部误用;while和do-while需要手动维护迭代变量j和k,且循环结束后变量仍保留。do-while在此场景中与while结果一致,因为初始值2满足条件,循环体必然执行。若初始值改为101,while循环0次执行,do-while仍执行1次(累加101),体现两者本质差异。
i++);② 检查条件是否永远为true(如while(true)但无break出口);③ 浮点数循环变量因精度问题可能无法精确到达终止值;④ 嵌套循环中内层循环修改了外层循环的迭代变量。
4.3 break与continue:循环的精确控制
4.3.1 核心原理
break用于立即终止当前所在循环或switch语句,程序跳转到循环外的下一条语句;continue用于跳过当前循环迭代中剩余的代码,直接进入下一次迭代的条件判断。两者均只作用于最近一层的循环结构,若需跳出多层嵌套循环,可使用带标签的break(如outer: for(...){ ... break outer; })。
4.3.2 使用规则与操作流程
- break使用场景:在循环中搜索到目标元素后提前退出,避免无效迭代;在switch中防止case穿透。
- continue使用场景:跳过不符合条件的元素(如只处理奇数),或跳过循环体尾部的某些操作。
- 标签语法:
标签名: 循环语句,break/continue后跟标签名可跳转到指定层。
// 示例:查找数组中第一个大于50的数并输出其索引
int[] arr = {12, 45, 67, 89, 23};
int targetIndex = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] > 50) {
targetIndex = i;
break; // 找到后立即终止循环
}
}
System.out.println("第一个大于50的索引: " + targetIndex);
// 示例:输出1-10中所有奇数(跳过偶数)
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // 跳过偶数,不执行后续打印
}
System.out.print(i + " ");
}
// 输出: 1 3 5 7 9
4.3.3 案例拆解:素数检测与嵌套循环控制
场景:输出2到50之间的所有素数。要求使用嵌套循环,内层循环判断是否为素数,外层循环遍历候选数字,并利用break优化性能。
for (int num = 2; num <= 50; num++) {
boolean isPrime = true;
// 只需检查到sqrt(num)即可,减少循环次数
for (int divisor = 2; divisor <= Math.sqrt(num); divisor++) {
if (num % divisor == 0) {
isPrime = false;
break; // 已确定非素数,立即终止内层循环
}
}
if (isPrime) {
System.out.print(num + " ");
}
}
// 输出: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
案例复盘:内层循环使用break在发现第一个因子时立即退出,避免继续检查更大的除数,时间复杂度从O(n²)优化为O(n√n)。外层循环通过isPrime标志位判断是否打印。此案例展示了break在嵌套循环中的典型应用——提前终止内层循环,同时外层循环继续执行。若需同时终止外层循环,则需使用带标签的break。
4.4 综合对比与应试要点
| 对比维度 | if-else | switch | for | while | do-while |
|---|---|---|---|---|---|
| 判断条件类型 | boolean表达式 | 等值匹配(int/String等) | boolean表达式(循环条件) | ||
| 执行次数 | 单次分支 | 单次分支 | 0~N次 | 0~N次 | 至少1次 |
| 典型应用 | 区间判断、复合条件 | 菜单选择、状态机 | 数组遍历、计数 | 条件循环、文件读取 | 先执行后验证 |
| break作用 | 不适用 | 防止穿透 | 终止当前循环 | ||
| continue作用 | 不适用 | 不适用 | 跳过本次迭代剩余语句 | ||
二级考试高频考点:
- if-else的悬空else问题:else与最近的if配对。
- switch的case穿透现象:省略break时,后续case会依次执行。
- for循环的初始化表达式可省略,但分号不能省略(
for(;;)为死循环)。 - while与do-while的区别:do-while末尾必须有分号。
- break与continue在嵌套循环中的作用层级。
- 循环变量作用域:for循环内定义的变量在循环外不可访问。
for(int i=0; i<10; i++){ if(i==5) continue; System.out.println(i); }输出0-9中除5以外的数字,共9个;② while(false){ }不执行循环体,但do{ }while(false);执行一次;③ switch中default位置可放在任意位置,但通常放在最后;④ 循环条件中比较浮点数时,应使用差值值小于阈值的方式判断。
4.5 实战综合案例:简易ATM取款机逻辑
背景与约束:模拟ATM取款流程,初始余额1000元。要求:用户输入取款金额,若金额大于余额则提示错误并重新输入;若金额为负数或0则提示非法;每次取款后显示剩余余额;用户输入0时退出系统。需使用do-while保证至少显示一次菜单,使用while处理非法输入,使用break退出循环。
import java.util.Scanner;
public class ATMSimulator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double balance = 1000.0;
int choice;
do {
System.out.println("当前余额: " + balance);
System.out.println("请输入取款金额(输入0退出): ");
choice = scanner.nextInt();
if (choice == 0) {
break; // 退出循环
}
if (choice < 0) {
System.out.println("金额不能为负数!");
continue; // 跳过本次迭代,重新输入
}
if (choice > balance) {
System.out.println("余额不足!");
continue;
}
balance -= choice;
System.out.println("取款成功,剩余余额: " + balance);
} while (true); // 通过break控制退出
System.out.println("感谢使用,再见!");
scanner.close();
}
}
案例拆解:
- 初始现象:用户可能输入非法金额(负数、超余额),需要循环校验。
- 关键设计:do-while保证菜单至少显示一次;break在输入0时立即退出;continue跳过非法输入后的余额扣减逻辑。
- 风险与代价:若用户持续输入非法值,循环不会退出,需提供明确的退出方式(输入0)。
- 复盘经验:循环控制语句的合理组合能实现清晰的用户交互逻辑。实际ATM系统还需考虑超时退出、交易记录等,此处仅演示核心流程控制。
流程控制语句是Java程序逻辑的骨架,熟练掌握if-else、switch、for、while、do-while以及break、continue的组合运用,能够应对绝大多数编程场景。在考试中,建议先画出逻辑流程图再编写代码,注意边界条件(如0次循环、首次执行、临界值)的测试。通过本章的案例拆解与对比表格,考生应能准确判断不同场景下的最优语句选择,并规避常见的语法陷阱。