switch 表达式#
版本信息
- 最低 JDK:14(12/13 预览 → 14 正式,17 LTS GA)
- JEP:JEP 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 -> "另一类";
};
}
}
- :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,不是return:case X -> { log(); yield v; }。 - 与「switch 模式匹配」(JDK 21,按类型而非常量分支)是两件事,别混淆;后者见 模式匹配与 record 解构。
- 老的冒号形式仍可用,但新代码首选箭头形式。
小结#
switch 表达式是低风险高收益的升级:消除 fall-through bug、更声明式、可直接赋值。