Menu

Java switch 语句:case、穿透与箭头语法

Java switch 语句详解:case 标签、break 与穿透、default 分支、合并多个 case、新式箭头写法,以及 switch 表达式。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

switch 的用途

switch 把一个值和一组固定选项逐一比较,然后执行匹配的那个分支。如果你发现自己在写一长串 if/else if,而且每次都在拿同一个变量和不同的常量比较,那么用 switch 能把同样的意思表达得更清楚。

它只能和编译期常量做相等比较,不能判断范围,也不能组合多个条件。遇到这些情况,还是用 if/else。

传统的 switch 语句

传统写法使用带冒号的 case 标签,并在每个分支后面加一个 break:

Java 先计算 day 的值,跳到匹配的 case,执行其中的语句,然后 break 退出 switch。没有任何分支匹配时,就执行 default 分支,你可以把它看作 else。它是可选的,但最好写上,这样意料之外的值就不会悄无声息地溜过去。

break 的陷阱:穿透

这是 switch 最常见的 bug。如果漏写了 break,程序不会在匹配的 case 结束时停下来,而是会“穿透”到下一个 case,一直执行到遇到 break 或右花括号为止:

你可能以为只会输出 Level 1,但实际上三行都会打印出来。因为 case 1 没有 break,控制流直接滑进了 case 2 和 case 3。除非你确实需要穿透,否则一定要加 break;如果真的要依赖穿透,请写一条注释,让后来读代码的人知道这是故意的。

合并多个 case

穿透有一个合理又整洁的用法:把多个 case 标签叠在一起,让几个值共用同一段代码。把这些标签紧挨着写,中间不放任何代码:

这里 'A'、'B' 和 'C' 都会执行同一行 "Pass"。这正是表达“这些值中的任何一个都做同样的事”的推荐写法。

对字符串使用 switch

switch 不只能用于数字。从 Java 7 开始,你可以对 String 使用 switch,非常适合处理菜单选项或命令名:

匹配区分大小写:"Stop" 不会匹配 "stop",所以如果输入的大小写不固定,请先统一处理(例如 command.toLowerCase())。还有一个坑:如果 command 是 null,switch 会抛出 NullPointerException,所以在执行到它之前要先排除 null。

新式箭头语法

较新的 Java(14 及以上)新增了箭头写法 case label -> ...,从设计上解决了穿透问题。每个箭头 case 只执行一个分支,永远不会穿透,所以也就没有会被忘掉的 break:

注意,这里用逗号合并多个值(case 6, 7),而不是叠放标签,而且整段代码里一个 break 都没有。如果一个分支有多条语句,就用代码块:case 1 -> { ...; ... }。新代码建议优先使用这种写法,它更简短,也消除了一整类 bug。

作为表达式的 switch

箭头写法还能“产生一个值”。switch 表达式会返回一个结果,你可以直接把它赋给变量,不需要临时变量,也不用在每个分支里重复赋值:

整个 switch (...) { ... } 计算出一个数字,存进 days。注意右花括号后面的分号,它是这条赋值语句的一部分。switch 表达式必须是穷尽的(覆盖所有可能的值),这就是这里要写 default 的原因。还要注意,没有匹配的分支可以抛出异常,而不是返回一个值。如果某个分支在返回值之前需要执行多条语句,就使用带 yield 的代码块:

case 2 -> {
    boolean leap = (year % 4 == 0);
    yield leap ? 29 : 28;
}

yield 是箭头代码块交回结果的方式,相当于表达式世界里带着结果的 break。

下一页:for 循环

switch 从多个分支中选出一个;而有时你需要把一段代码重复执行很多次。for 循环可以按受控的次数运行代码,比如在一个范围内计数,或逐个遍历每一项,这就是下一页的内容。

常见问题

Java 中什么时候用 switch 代替 if-else?

当你要把一个值和许多固定的常量选项进行比较时,就用 switch,比如星期几的编号、菜单选项或一个 enum。它比一长串 if/else if 更清晰,也明确表达了“从这些已知的值中选一个分支”。如果条件涉及范围(x > 10)、多个变量,或者不是和常量做简单的相等比较,就继续用 if/else。

为什么 Java switch 语句里需要 break?

在传统的冒号写法中,一旦某个 case 匹配成功,程序就会继续往下执行后面的 case,直到遇到 break 或 switch 结束,这就是穿透。break 用来阻止它。忘了写它是经典 bug:你匹配了 case 1:,却意外地把 case 2:、case 3: 等的代码也执行了。新的箭头语法(case 1 -> ...)从不穿透,所以根本不用写 break。

Java 的 switch 语句可以用于字符串吗?

可以。从 Java 7 开始,switch 可以作用于 String,也可以作用于 int、char、byte、short、它们的包装类型以及 enum 值。但不能用于 long、double、float 或 boolean。字符串匹配区分大小写,所以 "Yes" 和 "yes" 是不同的 case。

Coddy 编程语言插图

和 Coddy 一起学编程

开始