第 8 章:流程控制 — 分支结构
学习目标
- 掌握 if-else 三种写法
- 掌握 switch 传统语法和 JDK 14+ 新语法
- 理解分支结构的本质:让程序根据条件选择执行路径
一、为什么需要分支?
现实世界充满"如果...就..."的决策:
程序也需要做决策——这就是分支结构。
二、if-else 三种形式
2.1 单 if
java
int age = 18;
if (age >= 18) { // ① 条件为 true 时执行
System.out.println("可以投票");
}2.2 if-else 二选一
java
if (age >= 18) {
System.out.println("成年");
} else { // ① 条件为 false 时执行
System.out.println("未成年");
}2.3 if-else if-else 多选一
java
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) { // ① 多个条件依次判断
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}执行流程:
2.4 嵌套 if
java
if (age >= 18) {
if (hasId) {
System.out.println("可以买酒");
} else {
System.out.println("需要带身份证");
}
} else {
System.out.println("未成年不能买酒");
}嵌套层级
嵌套不要超过 3 层,否则可读性暴跌。可以用卫语句(guard clause)优化:
java// ✅ 卫语句:先处理特殊情况,提前返回 if (age < 18) { System.out.println("未成年不能买酒"); return; } if (!hasId) { System.out.println("需要带身份证"); return; } System.out.println("可以买酒");
三、switch 传统语法
适用于等值判断(一个变量等于多个固定值之一)。
3.1 基本语法
java
int day = 3;
String dayName;
switch (day) { // ① switch 后是变量
case 1: // ② case 标签:等值匹配
dayName = "周一";
break; // ③ 必须 break,否则穿透
case 2:
dayName = "周二";
break;
case 3:
dayName = "周三";
break;
case 4:
dayName = "周四";
break;
case 5:
dayName = "周五";
break;
case 6:
case 7: // ④ 多个 case 共用一个代码块
dayName = "周末";
break;
default: // ⑤ 默认分支(类似 else)
dayName = "无效";
}
System.out.println(dayName); // 周三3.2 switch 支持的类型
java
// 支持:byte / short / int / char / String / enum
switch (month) { ... } // int
switch (grade) { ... } // char
switch ("hello") { ... } // String(JDK 7+)
switch (DayOfWeek.MONDAY) {} // enum
// ❌ 不支持:long / float / double / boolean3.3 break 穿透问题
java
// ❌ 没有 break,会从匹配的 case 一直执行到 switch 结束
int x = 2;
switch (x) {
case 1:
System.out.println("1");
case 2: // 命中这里
System.out.println("2"); // 输出
case 3:
System.out.println("3"); // 也输出(穿透!)
case 4:
System.out.println("4"); // 也输出(穿透!)
}
// 输出:2 3 4实际开发中的穿透
大部分情况必须 break。但多个 case 共享代码块时可以利用穿透:
javacase 6: case 7: // 共享代码块 dayName = "周末"; break;这是有意为之的穿透,不是 bug。
四、switch 增强语法(JDK 14+)
JDK 14 引入了箭头语法 case X ->,彻底解决穿透问题:
java
int day = 3;
String dayName = switch (day) {
case 1 -> "周一";
case 2 -> "周二";
case 3 -> "周三";
case 4 -> "周四";
case 5 -> "周五";
case 6, 7 -> "周末"; // ① 多个值用逗号分隔
default -> "无效"; // ② 默认分支
};
System.out.println(dayName); // 周三4.1 箭头语法的优势
| 特性 | 传统语法 | 箭头语法 |
|---|---|---|
break | 必须 | 自动不穿透 |
| 多个值 | 用穿透 | 用逗号 |
| 返回值 | 不支持 | 支持作为表达式 |
| 代码量 | 多 | 少 50% |
4.2 switch 表达式(JDK 14+)
箭头语法让 switch 成为表达式(有返回值):
java
// 直接返回值
String season = switch (month) {
case 3, 4, 5 -> "春";
case 6, 7, 8 -> "夏";
case 9, 10, 11 -> "秋";
case 12, 1, 2 -> "冬";
default -> throw new IllegalArgumentException("月份无效: " + month);
};需要复杂逻辑时用 yield 返回:
java
String level = switch (score / 10) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> "C";
case 6 -> "D";
default -> {
if (score < 0) {
yield "无效"; // yield 用于复杂分支
}
yield "E";
}
};五、if-else vs switch 选择
| 场景 | 推荐 |
|---|---|
| 范围判断(score >= 90) | if-else |
| 等值判断(day == 3) | switch |
| 复杂条件组合 | if-else |
| 枚举值判断 | switch |
java
// ✅ 范围用 if
if (score >= 90) { ... }
if (age >= 18 && hasId) { ... }
// ✅ 等值用 switch
switch (status) {
case "PENDING": ...
case "PAID": ...
}六、完整代码示例
java
/**
* 分支结构综合示例
*
* 配套文档:第 8 章 流程控制 - 分支结构
* 运行方式:javac BranchDemo.java && java BranchDemo
*/
public class BranchDemo {
public static void main(String[] args) {
// ============ 1. if-else 多选一 ============
System.out.println("=== if-else ===");
int score = 85;
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
// ============ 2. 卫语句优化嵌套 ============
System.out.println("\n=== 卫语句 ===");
int age = 20;
boolean hasId = true;
printBuyResult(age, hasId);
// ============ 3. switch 传统语法 ============
System.out.println("\n=== switch 传统 ===");
int day = 6;
String dayName;
switch (day) {
case 1: dayName = "周一"; break;
case 2: dayName = "周二"; break;
case 3: dayName = "周三"; break;
case 4: dayName = "周四"; break;
case 5: dayName = "周五"; break;
case 6:
case 7: dayName = "周末"; break;
default: dayName = "无效";
}
System.out.println("day " + day + " = " + dayName);
// ============ 4. switch 箭头语法(JDK 14+)============
System.out.println("\n=== switch 箭头 ===");
String dayName2 = switch (day) {
case 1 -> "周一";
case 2 -> "周二";
case 3 -> "周三";
case 4 -> "周四";
case 5 -> "周五";
case 6, 7 -> "周末";
default -> "无效";
};
System.out.println("day " + day + " = " + dayName2);
// ============ 5. switch 表达式 ============
System.out.println("\n=== switch 表达式 ===");
int month = 7;
String season = switch (month) {
case 3, 4, 5 -> "春";
case 6, 7, 8 -> "夏";
case 9, 10, 11 -> "秋";
case 12, 1, 2 -> "冬";
default -> "未知";
};
System.out.println(month + "月是" + season + "季");
}
/**
* 卫语句演示:先处理特殊情况,提前返回
*/
public static void printBuyResult(int age, boolean hasId) {
if (age < 18) { // ① 特殊情况 1
System.out.println("未成年不能买酒");
return;
}
if (!hasId) { // ② 特殊情况 2
System.out.println("需要带身份证");
return;
}
System.out.println("可以买酒"); // ③ 正常情况
}
}七、常见面试题
Q1: switch 能用 String 吗?
JDK 7+ 可以:
java
String cmd = "start";
switch (cmd) {
case "start": ...
case "stop": ...
}原理:编译器把 String 转换为 hashCode() + equals() 比较。
Q2: switch 和 if-else 哪个快?
- 分支少(< 4):if-else 更快
- 分支多(≥ 4):switch 用跳转表(jump table),O(1) 快
Q3: default 必须有吗?
不必须,但强烈建议。default 处理意料外的值,避免程序行为未定义。
八、本章小结
| 要点 | 关键 |
|---|---|
| if-else | 范围判断 / 复杂条件,嵌套不超过 3 层 |
| 卫语句 | 先处理特殊情况,提前 return |
| switch | 等值判断,分支多用跳转表更快 |
| JDK 14+ | 箭头语法 case X ->,无 break,自动不穿透 |
| switch 表达式 | 直接返回值,复杂分支用 yield |
动手练习
练习 1:基础题
写一个 BMI 计算器:
java
double height = 1.75; // 米
double weight = 70; // 公斤
double bmi = weight / (height * height);
// BMI < 18.5: 偏瘦
// 18.5 ~ 24: 正常
// 24 ~ 28: 偏胖
// >= 28: 肥胖练习 2:进阶题
写一个计算器,支持 + - × ÷:
java
int a = 10, b = 3;
char op = '+';
// 用 switch 计算结果练习 3:挑战题
用 JDK 14+ 箭头语法实现一个生肖判断:
java
int year = 2026;
// 输出:生肖是马推荐阅读
- 📖 《Java 核心技术》卷 1 第 3.6 节 — 控制流程
- 🌐 JEP 361: Switch Expressions — JDK 14 switch 表达式提案
下一章:第 9 章:流程控制 — 循环结构 →