跳转至

switch 表达式#

版本信息

  • 最低 JDK:14(12/13 预览 → 14 正式,17 LTS GA)
  • JEPJEP 361

为什么需要#

JDK 8 的 switch 是语句(statement),易忘 break 导致 fall-through 穿透 bug,且不能直接赋值。switch 表达式用箭头 -> 无穿透、可直接返回值、对枚举强制穷尽,更安全也更简洁。

语法#

package com.javamodern.switchexpr;

public class SwitchDemo {
    enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }

    public static void main(String[] args) {
        System.out.println(classify(Day.FRIDAY));
    }

    static String classify(Day day) {
        return switch (day) {                       // (1)
            case MONDAY, FRIDAY, SUNDAY -> "特殊日";
            case TUESDAY, WEDNESDAY -> "工作日";
            case THURSDAY, SATURDAY -> "另一类";
        };
    }
}
  1. :material-lightbulb: switch (day) 作为表达式直接返回;箭头分支 -> 无穿透,枚举必须穷尽所有取值(否则编译报错)。

与 JDK 8 旧写法对比#

String r;
switch (day) {
    case MONDAY: case FRIDAY: case SUNDAY: r = "特殊日"; break;
    case TUESDAY: r = "工作日"; break;
    case WEDNESDAY: r = "工作日"; break;
    case THURSDAY: case SATURDAY: r = "另一类"; break;
    default: throw new IllegalArgumentException();
}
String r = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> "特殊日";
    case TUESDAY, WEDNESDAY -> "工作日";
    case THURSDAY, SATURDAY -> "另一类";
};

底层原理#

箭头分支编译为 tableswitch/lookupswitch(与旧 switch 同等字节码效率),区别在编译器强制:无 fall-through、多标签一行、枚举穷尽性。yield 关键字用于在块分支中返回值。

graph LR
    E["switch 表达式"] --> A["箭头分支: 无穿透"]
    E --> Y["块分支: 用 yield 返回"]
    E --> X["枚举: 强制穷尽"]
    style E fill:#bbdefb

常见坑 / 最佳实践#

  • 块分支里返回值用 yield,不是 returncase X -> { log(); yield v; }
  • 与「switch 模式匹配」(JDK 21,按类型而非常量分支)是两件事,别混淆;后者见 模式匹配与 record 解构
  • 老的冒号形式仍可用,但新代码首选箭头形式。

小结#

switch 表达式是低风险高收益的升级:消除 fall-through bug、更声明式、可直接赋值。

参考#