使用枚举的 switch 表达式
使用现代 switch 表达式处理枚举,实现清晰且覆盖完整的分支逻辑
使用枚举的 switch 表达式 是 CoddyKit 上的免费 Java Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
使用枚举的 switch 表达式
使用枚举的 switch 表达式(Java 14+)可以进行完整、简洁的基于类型的路由。当所有枚举常量都已覆盖时,不需要 default。
传统 switch 语句
经典的 switch 语句支持枚举,但需要使用 break 来防止分支贯穿执行。
enum Severity { LOW, MEDIUM, HIGH, CRITICAL }
Severity s = Severity.HIGH;
String action;
switch (s) {
case LOW:
action = "Log and monitor";
break;
case MEDIUM:
action = "Notify on-call team";
break;
case HIGH:
action = "Page engineer immediately";
break;
case CRITICAL:
action = "Activate incident response";
break;
default:
action = "Unknown";
}
System.out.println(action); // Page engineer immediately带箭头标签的 switch 表达式
带箭头标签的 switch 表达式可以消除分支贯穿执行和 break。它们会计算出一个值,并且要求覆盖所有情况。
enum Severity { LOW, MEDIUM, HIGH, CRITICAL }
Severity s = Severity.HIGH;
String action = switch (s) {
case LOW -> "Log and monitor";
case MEDIUM -> "Notify on-call team";
case HIGH -> "Page engineer immediately";
case CRITICAL -> "Activate incident response";
// no default needed — all cases covered
};
System.out.println(action); // Page engineer immediately带代码块的 switch 表达式
当 case 逻辑需要执行多条语句时,请使用带 yield 的代码块来生成结果值。
enum DayOfWeek { MON, TUE, WED, THU, FRI, SAT, SUN }
DayOfWeek day = DayOfWeek.FRI;
int hoursOpen = switch (day) {
case MON, TUE, WED, THU -> 8;
case FRI -> {
System.out.println("Half day on Friday!");
yield 4; // yield returns value from block
}
case SAT, SUN -> 0;
};
System.out.println("Hours open: " + hoursOpen); // Hours open: 4对多个分支进行分组
多个枚举常量可以使用逗号分隔,共享同一个分支。
enum Season { SPRING, SUMMER, FALL, WINTER }
Season season = Season.SUMMER;
String activity = switch (season) {
case SPRING, FALL -> "Hike in the mountains";
case SUMMER -> "Beach vacation";
case WINTER -> "Ski at the resort";
};
System.out.println(activity); // Beach vacation在方法中通过 switch 返回
switch 表达式非常适合作为方法的 return 语句使用,能够清晰地表达意图。
enum Priority { LOW, NORMAL, HIGH, URGENT }
static int getSlaHours(Priority p) {
return switch (p) {
case LOW -> 72;
case NORMAL -> 24;
case HIGH -> 4;
case URGENT -> 1;
};
}
System.out.println(getSlaHours(Priority.URGENT)); // 1
System.out.println(getSlaHours(Priority.LOW)); // 72流中的 switch 表达式
switch 表达式可以在流操作中使用,以便对每个元素进行简洁的转换。
import java.util.*;
import java.util.stream.*;
enum Status { PENDING, ACTIVE, CLOSED }
record Account(String id, Status status) {}
List<Account> accounts = List.of(
new Account("A1", Status.ACTIVE),
new Account("A2", Status.PENDING),
new Account("A3", Status.CLOSED)
);
accounts.stream()
.map(a -> a.id() + ": " + switch (a.status()) {
case ACTIVE -> "\u2705 Live";
case PENDING -> "\u23f3 Awaiting activation";
case CLOSED -> "\u274c Deactivated";
})
.forEach(System.out::println);编译时的穷尽性检查
编译器会强制要求覆盖所有枚举常量。向枚举中添加新常量后,所有未处理该常量的 switch 表达式都会产生编译错误。
enum Color { RED, GREEN, BLUE } // add YELLOW here → compile error below
Color c = Color.GREEN;
// This switch is exhaustive for RED, GREEN, BLUE
// If you add YELLOW to the enum without adding a case here,
// the compiler will report an error.
String hex = switch (c) {
case RED -> "#FF0000";
case GREEN -> "#00FF00";
case BLUE -> "#0000FF";
};
System.out.println(hex); // #00FF00使用默认分支确保安全
使用 switch 语句而非表达式时,或者有意只覆盖部分分支时,请添加默认分支。
enum Feature { DARK_MODE, PUSH_NOTIFICATIONS, ANALYTICS, BETA_FEATURE }
static boolean isEnabled(Feature feature) {
return switch (feature) {
case DARK_MODE, PUSH_NOTIFICATIONS -> true;
case ANALYTICS -> false;
default -> {
System.out.println("Unknown feature: " + feature);
yield false;
}
};
}
System.out.println(isEnabled(Feature.DARK_MODE)); // true
System.out.println(isEnabled(Feature.BETA_FEATURE)); // false实践:订单生命周期
使用 switch 表达式确定允许转换的完整订单生命周期状态机。
enum OrderState { CART, PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED }
static Set<OrderState> allowedTransitions(OrderState from) {
return switch (from) {
case CART -> Set.of(OrderState.PENDING, OrderState.CANCELLED);
case PENDING -> Set.of(OrderState.CONFIRMED, OrderState.CANCELLED);
case CONFIRMED -> Set.of(OrderState.SHIPPED);
case SHIPPED -> Set.of(OrderState.DELIVERED);
case DELIVERED, CANCELLED -> Set.of(); // terminal states
};
}
System.out.println(allowedTransitions(OrderState.PENDING));
// [CONFIRMED, CANCELLED]String 与枚举的 switch 对比
对 String 使用 switch 时,需要进行空值检查,并且区分大小写。对枚举使用 switch 时可以安全处理空值(值为 null 时会产生 NPE),并且具有类型安全性——当值集合已知时,优先使用枚举。
// String switch — fragile
String role = "admin";
String label = switch (role.toLowerCase()) {
case "admin" -> "Administrator";
case "guest" -> "Guest User";
default -> "Unknown";
};
// Enum switch — type-safe
enum Role { ADMIN, GUEST }
Role r = Role.ADMIN;
String label2 = switch (r) {
case ADMIN -> "Administrator";
case GUEST -> "Guest User";
};
System.out.println(label2); // Administrator快速检查
您有一个包含 4 个常量的枚举,并编写了覆盖全部 4 个常量的 switch 表达式。如果向该枚举中添加第 5 个常量,会发生什么?
回顾:使用枚举的 switch 表达式
要点:
- 带箭头标签的 switch 表达式无需使用 break,也不会发生贯穿
- 使用 yield 从块分支中返回值
- 使用逗号将多个常量分组:case A, B ->
- 覆盖所有常量的穷尽式 switch 表达式不需要默认分支
- 添加新的枚举常量会使穷尽式 switch 表达式产生编译错误
- switch 表达式非常适合用于流的 map() 操作
常见问题解答
「使用枚举的 switch 表达式」课时是免费的吗?
是的 — 「使用枚举的 switch 表达式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「使用枚举的 switch 表达式」这节课中我会学到什么?
使用现代 switch 表达式处理枚举,实现清晰且覆盖完整的分支逻辑 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「使用枚举的 switch 表达式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 定义和使用枚举
- 带字段和方法的枚举
- 使用枚举的 switch 表达式
- EnumSet 与 EnumMap