Skip to content
第 8 / 250 章后端⏱ 10 分钟阅读

第 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 / boolean

3.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 共享代码块时可以利用穿透:

java
case 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;
// 输出:生肖是马

推荐阅读


下一章第 9 章:流程控制 — 循环结构

本站基于 VitePress 构建 · 由 Codebook 团队维护