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 块,直到遇到 breakswitch 结束。

来看一个没有 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 并不支持所有类型,它仅支持以下几种:

✅ 基本类型及其包装类:byteshortintchar
✅ 枚举类型(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()

switchString 的比较是基于 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 上的完整示例代码:


原始标题:Java Switch Statement | Baeldung