switch 语句是一种多路分支结构,它根据一个变量的值来决定执行哪一段代码,它可以看作是 if-else if-else 链的一种更清晰、更高效的替代方案,尤其是在处理多个离散值的情况下。

基本语法
switch 语句的基本结构如下:
switch (expression) {
case value1:
// 当 expression 的值等于 value1 时,执行这里的代码
break; // 可选,用于跳出 switch 语句
case value2:
// 当 expression 的值等于 value2 时,执行这里的代码
break; // 可选
case value3:
// 当 expression 的值等于 value3 时,执行这里的代码
break; // 可选
// 可以有任意数量的 case
default:
// expression 的值不匹配任何一个 case,则执行这里的代码
break; // 可选,但通常建议加上
}
执行流程:
- 计算
switch后面的expression的值。 - 将这个值与每个
case后面的value进行比较。 - 如果找到匹配的
case,程序就跳转到该case标签,并开始执行其后的代码。 - 如果没有找到匹配的
case,程序会跳转到default标签(如果存在)并执行其后的代码。 break关键字:非常重要,当执行到break时,程序会立即退出整个switch语句,如果省略break,程序会继续执行下一个case的代码,这被称为 “贯穿” (fall-through)。
代码示例
示例 1:基本用法(带 break)
这是最常见的用法,根据输入的星期数输出对应的英文。
public class SwitchExample {
public static void main(String[] args) {
int day = 3;
String dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
case 6:
dayName = "Saturday";
break;
case 7:
dayName = "Sunday";
break;
default: // 处理 day 不在 1-7 范围内的情况
dayName = "Invalid day";
break;
}
System.out.println("The day is: " + dayName);
}
}
// 输出: The day is: Wednesday
示例 2:贯穿 效果(不带 break)
有时,我们需要多个 case 执行相同的代码块,这时可以利用“贯穿”特性。

public class SwitchFallThrough {
public static void main(String[] args) {
char grade = 'B';
switch (grade) {
case 'A':
System.out.println("Excellent!");
break;
case 'B':
case 'C':
System.out.println("Good job!"); // grade 是 'B' 或 'C' 时都会执行这句
break;
case 'D':
System.out.println("You passed.");
break;
case 'F':
System.out.println("Better luck next time.");
break;
default:
System.out.println("Invalid grade.");
break;
}
}
}
// 输出: Good job!
注意:在现代 Java 开发中,如果你没有使用“贯穿”的意图,忘记写 break 是一个非常常见的错误,会导致逻辑混乱,一些代码检查工具(如 SonarLint)会警告未使用 break 的 case。
Java 7 的重要更新:支持 String 类型
在 Java 7 之前,switch 语句只能支持 int 类型及其包装类(Integer)、char 类型以及枚举(Enum),从 Java 7 开始,switch 语句开始支持 String 类型。
底层原理:Java 编译器在编译时会将 String 类型的 switch 转换为对 String.hashCode() 的调用,然后使用 if-else 结构对 hashCode 的结果和每个 case 的 String 的 hashCode 进行比较,最后再用 equals() 方法来确保精确匹配(因为不同的字符串可能有相同的 hashCode)。
示例:

public class SwitchWithString {
public static void main(String[] args) {
String fruit = "Apple";
switch (fruit) {
case "Apple":
System.out.println("Selected fruit is Apple.");
break;
case "Banana":
System.out.println("Selected fruit is Banana.");
break;
case "Orange":
System.out.println("Selected fruit is Orange.");
break;
default:
System.out.println("Unknown fruit.");
break;
}
}
}
// 输出: Selected fruit is Apple.
Java 14 的重要更新:switch 表达式
从 Java 14 开始,switch 有了一种新的形式——switch 表达式,它不仅是语句,更是一个表达式,意味着它可以返回一个值,并且消除了“贯穿”的复杂性。
关键特性:
- 返回值:整个
switch可以有一个返回值。 - 箭头
->:使用->代替 ,每个case的代码块更加简洁,并且默认不会“贯穿”,如果需要“贯穿”,必须使用yield关键字显式声明。 yield:用于在switch表达式中返回一个值。
示例 3:传统 switch 语句 vs. switch 表达式
假设我们要根据成绩等级返回绩点。
// 传统 switch 语句
double getGpaOld(char grade) {
switch (grade) {
case 'A': return 4.0;
case 'B': return 3.0;
case 'C': return 2.0;
case 'D': return 1.0;
default: return 0.0;
}
}
// Java 14+ 的 switch 表达式
double getGpaNew(char grade) {
return switch (grade) {
case 'A' -> 4.0;
case 'B' -> 3.0;
case 'C' -> 2.0;
case 'D' -> 1.0;
default -> 0.0;
};
}
switch 表达式中的“贯穿”处理:
如果多个 case 需要返回相同的值,或者需要执行多行代码再返回,可以使用大括号 和 yield。
int getLengthCategory(String text) {
return switch (text.length()) {
case 0, 1, 2 -> 1; // 处理多个值
case 3, 4, 5 -> {
System.out.println("Medium length text");
yield 2; // 必须使用 yield 返回值
}
default -> 3;
};
}
switch 语句 vs. if-else if-else
| 特性 | switch 语句 |
if-else if-else 语句 |
|---|---|---|
| 可读性 | 当检查多个离散、确定的值时,可读性更高。 | 适用于复杂的条件判断(范围、布尔逻辑等)。 |
| 数据类型 | byte, short, char, int, String, enum。 |
所有布尔表达式,非常灵活。 |
| 性能 | 在某些情况下(如 JVM 优化后)可能比一长串 if-else 更高效,但差异通常很小。 |
性能取决于条件的复杂性和顺序。 |
| “贯穿” | 有“贯穿”特性,既是优点(可共享代码)也是缺点(易出错)。 | 没有“贯穿”,每个 if 块是独立的。 |
| 返回值 | 传统 switch 是语句,不返回值。switch 表达式可以返回值。 |
if-else 本身不返回值,但可以嵌套三元运算符。 |
选择建议:
- 优先使用
switch:当你需要根据一个变量的多个确定值来执行不同逻辑时,例如处理菜单选项、命令、枚举状态等。 - 优先使用
if-else:当你的条件涉及范围判断(如x > 10 && x < 20)、布尔逻辑组合(如a && b || c)或者比较的是对象(如if (myObject == null))时。
- 基本用法:
switch(expression)配合case value:和break;。 default:处理所有case都不匹配的情况,是可选但推荐的好习惯。String支持:从 Java 7 开始支持,底层依赖hashCode()和equals()。switch表达式 (Java 14+):是更现代、更安全的写法,使用->且默认不贯穿,用yield返回值。- 与
if-else的选择:根据判断条件的类型(离散值 vs. 复杂条件)来决定使用哪个。
