1. 概述
在本教程中,我们将深入探讨 Java 中的 switch
语句,了解它的使用方式以及其在不同版本中的演进。
switch
语句的主要作用是替代多重嵌套的 if-else
结构,从而提升代码的可读性和结构清晰度。
✅ 自 Java 5 和 Java 7 以来,switch
语句支持的数据类型逐渐扩展
✅ Java 12 引入了实验性的 switch
表达式,Java 13 正式完善并发布
下面我们将通过实际代码示例,介绍:
switch
语句的基本用法break
语句的作用与注意事项switch
参数和case
值的类型限制String
类型在switch
中的比较机制- Java 13 中的
switch
表达式新特性
2. 使用示例
假设我们有如下嵌套的 if-else
代码:
public String exampleOfIF(String animal) {
String result;
if (animal.equals("DOG") || animal.equals("CAT")) {
result = "domestic animal";
} else if (animal.equals("TIGER")) {
result = "wild animal";
} else {
result = "unknown animal";
}
return result;
}
这段代码虽然逻辑清晰,但维护性差,可读性也不高。
使用 switch
语句重写后,代码结构更加清晰:
public String exampleOfSwitch(String animal) {
String result;
switch (animal) {
case "DOG":
result = "domestic animal";
break;
case "CAT":
result = "domestic animal";
break;
case "TIGER":
result = "wild animal";
break;
default:
result = "unknown animal";
break;
}
return result;
}
📌 switch
会将传入的 animal
与各个 case
进行比较,如果都不匹配,则执行 default
分支。
📌 break
用于跳出 switch
,防止“fall-through”现象。
3. break
语句的重要性
⚠️ 如果忘记写 break
,程序会继续执行后续的 case
块,直到遇到 break
或 switch
结束。
来看一个没有 break
的例子:
public void forgetBreakInSwitch(String animal) {
switch (animal) {
case "DOG":
System.out.println("domestic animal");
default:
System.out.println("unknown animal");
}
}
执行 forgetBreakInSwitch("DOG")
的输出是:
domestic animal
unknown animal
❌ 显然这不是我们想要的结果。
✅ 正确做法是每个 case
后面都加上 break
,除非你明确需要 fall-through 行为。
当然,我们也可以利用这个特性来合并多个 case
:
public String exampleOfSwitch(String animal) {
String result;
switch (animal) {
case "DOG":
case "CAT":
result = "domestic animal";
break;
case "TIGER":
result = "wild animal";
break;
default:
result = "unknown animal";
break;
}
return result;
}
4. switch
参数与 case
值的限制
4.1. 支持的数据类型
Java 中的 switch
并不支持所有类型,它仅支持以下几种:
✅ 基本类型及其包装类:byte
、short
、int
、char
✅ 枚举类型(enum)
✅ 字符串类型(String) —— Java 7 开始支持
4.2. 禁止使用 null
❌ 传入 null
作为 switch
参数会抛出 NullPointerException
:
@Test(expected=NullPointerException.class)
public void whenSwitchAgumentIsNull_thenNullPointerException() {
String animal = null;
Assert.assertEquals("domestic animal", s.exampleOfSwitch(animal));
}
❌ case
标签也不能使用 null
,否则编译不通过。
4.3. case
值必须是编译时常量
case
后面的值必须是常量,或者被 final
修饰的变量:
final String dog = "DOG";
String cat = "CAT";
switch (animal) {
case dog: // ✅ 编译通过
result = "domestic animal";
case cat: // ❌ 编译失败
result = "feline";
}
4.4. String 比较基于 equals()
✅ switch
对 String
的比较是基于 equals()
方法的,而不是 ==
。
@Test
public void whenCompareStrings_thenByEqual() {
String animal = new String("DOG");
assertEquals("domestic animal", s.exampleOfSwitch(animal));
}
5. Java 13 中的 switch
表达式
Java 13 引入了改进版的 switch
表达式,语法更现代,功能更强大。
⚠️ 使用时需添加 --enable-preview
编译参数。
5.1. 新语法结构
var result = switch(month) {
case JANUARY, JUNE, JULY -> 3;
case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1;
case MARCH, MAY, APRIL, AUGUST -> 2;
default -> 0;
};
📌 使用 ->
替代 :
,自动 break,不会 fall-through
📌 支持多个条件用逗号分隔
5.2. 使用 yield
返回值
如果需要在 case
中执行多行逻辑,可以使用代码块配合 yield
关键字:
var result = switch (month) {
case JANUARY, JUNE, JULY -> 3;
case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1;
case MARCH, MAY, APRIL, AUGUST -> {
int monthLength = month.toString().length();
yield monthLength * 4;
}
default -> 0;
};
5.3. 不允许在表达式中 return
❌ 在 switch
表达式中不能使用 return
:
// ❌ 编译失败
var result = switch (month) {
case JANUARY, JUNE, JULY -> { return 3; }
default -> { return 0; }
};
✅ 但在 switch
语句中是可以的:
switch (month) {
case JANUARY, JUNE, JULY -> { return 3; }
default -> { return 0; }
}
5.4. 完整性检查
⚠️ switch
表达式要求覆盖所有可能的分支,否则编译不通过:
// ❌ 编译失败:缺少 default 或未覆盖所有情况
var result = switch (month) {
case JANUARY, JUNE, JULY -> 3;
case FEBRUARY, SEPTEMBER -> 1;
}
✅ 正确写法(覆盖所有情况):
var result = switch (month) {
case JANUARY, JUNE, JULY -> 3;
case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1;
case MARCH, MAY, APRIL, AUGUST -> 2;
}
6. 总结
switch
语句适用于枚举、有限状态等场景,能有效替代冗长的 if-else
结构。
✅ 优点:
- 代码结构清晰
- 易于维护
- Java 13+ 支持表达式语法,更加现代化
⚠️ 注意事项:
- 必须使用
break
防止 fall-through case
值必须是常量switch
参数不能为null
📌 如果条件分支频繁变动,建议使用多态或策略模式等设计模式来替代 switch
,以提高扩展性。
如需深入学习,可参考 GitHub 上的完整示例代码: