主题
Chapter 04 · 流程控制
让程序学会"思考":分支判断、循环执行、跳出与继续。
🎯 本章目标
- 用 if / else / else if 写出多条件判断
- 用 switch 简化多分支匹配(含 JDK 14 的箭头语法)
- 三种循环 for / while / do-while 各擅胜场
- 用 break / continue / return 跳出循环
- 知道 for-each 增强循环什么时候用
1. 分支结构:if / else
生活类比:早上出门看天气
天气晴 → 穿衬衫
天气阴 → 穿外套
天气雨 → 穿外套 + 带伞
其他 → 穿厚衣服翻译成 Java:
java
if (weather.equals("晴")) {
System.out.println("穿衬衫");
} else if (weather.equals("阴")) {
System.out.println("穿外套");
} else if (weather.equals("雨")) {
System.out.println("穿外套+带伞");
} else {
System.out.println("穿厚衣服");
}三个新手坑
java
// ❌ 坑 1:只写单语句不加大括号
if (age >= 18)
System.out.println("成年");
System.out.println("可投票"); // 这行其实和 if 无关,永远会执行
// ✅ 永远加大括号
if (age >= 18) {
System.out.println("成年");
System.out.println("可投票");
}java
// ❌ 坑 2:if (x = 5)(赋值!不是比较)
if (x = 5) { ... } // 编译错误(Java 严格类型,不像 C 会通过)
// ✅ Java 会拦你(Python 会让你哭)
if (x == 5) { ... }java
// ❌ 坑 3:用 == 比较 String
if (name == "张三") { ... } // 比较地址,可能 false
// ✅
if ("张三".equals(name)) { ... } // 把常量放前面避免空指针2. switch:多分支专家
传统写法(JDK 7 开始支持 String)
java
String day = "周三";
switch (day) {
case "周一":
case "周二":
case "周三":
case "周四":
case "周五":
System.out.println("工作日");
break;
case "周六":
case "周日":
System.out.println("周末");
break;
default:
System.out.println("非法日期");
}⚠️ 不写 break 会"穿透" —— 这是 switch 最大的坑,但偶尔也是特性(如上面合并周一到周五)。
新写法:箭头语法(JDK 14+)
java
String type = switch (day) {
case "周一", "周二", "周三", "周四", "周五" -> "工作日";
case "周六", "周日" -> "周末";
default -> "非法";
};更短、更安全,不需要 break,也不会穿透。
switch 支持的类型
| 版本 | 支持类型 |
|---|---|
| JDK 1.0 | byte / short / int / char |
| JDK 5 | + enum |
| JDK 7 | + String |
| JDK 14+ | 表达式形式(箭头语法) |
| JDK 21 | + 模式匹配(switch on instanceof) |
3. 循环:让重复的事情一句话搞定
3.1 for 循环(明确次数)
java
for (int i = 0; i < 5; i++) {
System.out.println("第 " + i + " 次");
}三段式:
- 初始化:
int i = 0(只执行一次) - 条件:
i < 5(每次循环前判断) - 步进:
i++(每次循环结束后执行)
3.2 while 循环(条件不定)
java
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}💡 何时用 while:循环次数不固定。比如"读文件直到读完"、"用户输错就重试"。
3.3 do-while(先做一次再说)
java
String input;
do {
input = scanner.nextLine(); // 至少要让用户输入一次
} while (!isValid(input));💡 何时用 do-while:至少要执行一次的场景,最典型是"输入校验"。
3.4 for-each 增强循环(遍历容器)
java
int[] nums = {1, 2, 3, 4, 5};
for (int n : nums) {
System.out.println(n);
}
// 也可以遍历集合
List<String> names = List.of("张三", "李四");
for (String name : names) {
System.out.println(name);
}| 用法对比 | for-each | 普通 for |
|---|---|---|
| 简洁 | ✅ | ❌ |
| 拿到下标 | ❌ | ✅ |
| 修改集合 | ❌(要用迭代器) | 可以 |
4. break / continue / return
| 关键字 | 作用 | 一句话 |
|---|---|---|
break | 跳出当前循环 | 结束本次比赛 |
continue | 跳过本次,进入下次 | 跳过这局,继续下一局 |
return | 退出整个方法 | 比赛队伍直接弃赛 |
java
for (int i = 0; i < 10; i++) {
if (i == 5) break; // i=5 时直接结束循环
if (i % 2 == 0) continue; // 偶数跳过本次
System.out.println(i); // 只打印 1, 3
}标签 break(跳出多重循环)
java
outer: // 给外层循环打标签
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i + j == 3) break outer; // 跳出两层循环
}
}5. 循环嵌套与性能
java
// 双层循环:n × m 次
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
// 这里执行 n*m 次
}
}经典应用:
| 场景 | 嵌套结构 |
|---|---|
| 九九乘法表 | i: 1~9, j: 1~i |
| 打印金字塔 | i: 行,j: 空格+星号 |
| 冒泡排序 | i: 趟数,j: 比较位置 |
| 二维数组遍历 | i: 行,j: 列 |
6. 实战练习
| 文件 | 内容 |
|---|---|
IfDemo.java | if/else 综合演示(成绩等级) |
SwitchDemo.java | switch 新旧两种语法 |
LoopDemo.java | for/while/do-while 对比 |
PrintShape.java | 嵌套循环打印图形 |
GuessNumber.java | 猜数字小游戏(综合实战) |
7. 浏览器演示
打开 demo.html 体验:
- 流程图可视化
- 在线猜数字游戏
- 九九乘法表生成器
8. 面试可能会问什么?
Q1: switch 支持哪些数据类型?
答:byte/short/int/char、String(JDK 7+)、enum(JDK 5+)。不支持 long、float、double、boolean。
Q2: switch 不写 break 会怎样?
答:会"穿透"(fall through),继续执行下一个 case 的代码块,直到遇到 break 或 switch 结尾。
Q3: for 和 while 有什么区别?
| 对比 | for | while |
|---|---|---|
| 适用 | 循环次数明确 | 循环条件不定 |
| 结构 | 三段式紧凑 | 只有条件 |
| 变量作用域 | 计数器只在 for 内可见 | 外部定义则外部可见 |
Q4: 增强 for(for-each)和普通 for 哪个快?
答:本质一样。for-each 编译后被翻译成迭代器(集合)或下标循环(数组),性能差距可忽略。但:
- 数组遍历优先用普通 for(可拿下标)
- 集合遍历优先用 for-each(更简洁)
Q5: 怎么从两层循环里跳出来?
答:用 标签 break:
java
outer:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (条件) break outer;
}
}或者把内层循环抽成方法,用 return。
Q6: do-while 和 while 的区别?
- while:先判断,可能一次都不执行
- do-while:先执行一次,再判断
Q7: 三元运算符能完全替代 if-else 吗?
答:不能。三元只能用作 表达式(产生值),不能用作语句(如多行操作)。
java
// ✅ 三元能做
int max = a > b ? a : b;
// ❌ 三元做不了(多行操作)
if (a > b) { System.out.println(a); doSomething(); }🎁 本章小结
✅ if-else 写多条件,永远加大括号
✅ switch 多分支匹配,新箭头语法更安全
✅ for 适合明确次数,while 适合不定次数
✅ for-each 简洁但拿不到下标
✅ break 跳出循环,continue 跳过本次,标签 break 跳多层🔗 导航
- ⬅️ 上一章:Chapter 03 · 运算符与表达式
- ➡️ 下一章:Chapter 05 · 数组