和 if/else 语句一样,switch 语句让你可以通过有条件地执行代码来改变程序的流程。
不同的是,switch 语句只能把基本类型或字符串表达式的值与预先定义的常量值进行比较。
使用 switch 语句时,有几个关键字很有用。
switch:这个关键字让你声明 switch 的结构。
它后面跟着会决定结果变化的表达式或变量。case:用它来声明结果的各种可能情况。break:break 关键字非常有用,可以在想要的分支结束时停止 switch 的执行。
如果忘了写,程序会继续执行,可能导致意外的结果。default:正如它的名字所示,当其他 case 都不匹配表达式的结果时,用它作为默认结果。最简单的 switch 语句会检查一个基本类型或字符串表达式,并根据它的值做出判断。 例如:
String direction = getDirection();
switch (direction) {
case "left":
goLeft();
break;
case "right":
goRight();
break;
default:
// otherwise
markTime();
break;
}
从 Java 14 开始(在此之前,Java 12 和 13 中已作为预览功能提供),可以使用“增强版”的 switch 实现。
你可以为单个 case 指定多个值。
在传统的 switch 语句中,你可以利用穿透。
在下面的例子中,case 1 和 case 3 会执行相同的代码。
这是通过让 case 1 不使用 break 关键字实现的。
switch (number) {
case 1:
case 3:
// do same stuff
break;
case 2:
// do different stuff
break;
// (...)
}
在增强版的 switch expression 中,你可以直接为 case 指定多个值。
看看下面的例子:
switch (number) {
case 1, 3:
// do stuff
break;
case 2:
// do other stuff
break;
// (...)
}
现在你可以写 switch-statement 或 switch expression。
区别是什么?
简单说,语句期待的是某种严格的逻辑,而表达式则可以返回一个值。
不用这样写:
String result = "";
switch (expression) {
case "bob":
result = "bob";
break;
// (...)
}
你可以这样写:
String result = switch (expression) {
case "bob":
yield "bob";
// (...)
}
yield 的作用类似于 return,只不过它是用于 switch 表达式的。
由于 yield 会终止表达式,所以这里不需要 break。
_switch 语句_和 _switch 表达式_的另一个区别:在 _switch 表达式_中,你 必须 覆盖所有情况。
要么为所有可能的值都写一个 case,要么使用一个 default 分支。
你可以用 -> 代替 :。
-> 让你可以省略 break 关键字。
两种写法都可以用,但在同一个 switch 中只能坚持用其中一种。
switch(expression) {
case 1 -> yield "one"
case 2 -> yield "two"
default: yield "other number" // Removing this will result in a compile error
}
作用域。
传统的 switch 因为作用域的缘故,可能导致一些意外的行为,因为整个 switch 只有一个作用域。
switch(expression) {
case 1:
String message = "something";
break;
case 2:
String message = "anything";
break;
// (...)
}
这个例子无法运行,因为 message 在 switch 中被声明了两次。
可以这样解决:
switch (expression) {
case 1: {
String message = "something";
break;
}
case 2: {
String message = "anything";
break;
}
// (...)
}
因为 {} 界定了 case 的作用域。
不过它并不直观,因为 {} 并不是必须的。
不过,如果你使用新的 -> 写法,它后面必须跟上以下之一:单条语句/表达式、throw 语句,或者一个 {} 块。
再也不会搞混了!
你可以在这篇文章和这一篇,以及官方的 Oracle 文档 中找到更多关于增强版 switch 的信息。
此外,Java 21 中新增了一个名为 Guarded Patterns 的特性,它允许你直接在 case 标签本身中进行检查。
String dayOfMonth = getDayOfMonth();
String day = "";
return switch (day) {
case "Tuesday" when dayOfMonth == 13 -> "Forbidden day!!";
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "Week day";
case "Saturday", "Sunday" -> "Weekend";
default -> "Unknown";
};
你可以在这篇博客中找到更多关于 Java 21 中 switch 表达式的信息。