杰瑞科技汇

Java switch 表达式与传统语句有何区别?

switch 语句到 switch 表达式

在 Java 12 之前,我们使用的是 switch 语句,它有几个明显的限制:

Java switch 表达式与传统语句有何区别?-图1
(图片来源网络,侵删)
  1. 只能执行操作,不能返回值switch 语句块内部不能直接返回一个值,通常我们用它来执行一系列操作,然后通过一个 break 跳出。
  2. break 容易出错:忘记写 break 会导致“贯穿”(fall-through)现象,这是一个常见的 Bug 来源。
  3. 语法冗长:对于简单的条件判断,if-else if 链可能更简洁。

从 Java 12 开始,引入了 switch 表达式,它解决了上述所有问题:

  • 可以返回值switch 表达式本身可以计算出一个值并返回。
  • 消除了“贯穿”switch 表达式要求每个 case 必须明确结束,要么使用 yield 返回一个值,要么使用 throw 抛出异常,这从根本上杜绝了“贯穿” Bug。
  • 语法更现代:支持更简洁的箭头 -> 语法,以及多常量标签。

switch 表达式的核心特性

返回值

switch 表达式可以像三元运算符或方法调用一样,将结果赋值给一个变量。

示例:

// JDK 12+
enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class SwitchExpressionExample {
    public static void main(String[] args) {
        Day day = Day.WEDNESDAY;
        // 使用 switch 表达式,并将结果赋值给 typeOfDay 变量
        String typeOfDay = switch (day) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Weekday";
            case SATURDAY, SUNDAY -> "Weekend";
        };
        System.out.println(day + " is a " + typeOfDay);
        // 输出: WEDNESDAY is a Weekday
    }
}

箭头 -> 语法

这是 switch 表达式最推荐的语法,箭头 -> 的右边是当 case 匹配时要执行的表达式或代码块。

Java switch 表达式与传统语句有何区别?-图2
(图片来源网络,侵删)
  • 如果右边是单个表达式(如上面的 "Weekday"),它会自动成为该 case 的返回值。
  • 如果右边是代码块(用 包围),则必须使用 yield 关键字来显式返回一个值。

示例(使用代码块和 yield):

Day day = Day.SATURDAY;
String typeOfDay = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
        // 可以在这里执行多条语句
        System.out.println("It's a weekday.");
        yield "Weekday"; // 必须使用 yield 返回值
    }
    case SATURDAY, SUNDAY -> {
        System.out.println("It's the weekend!");
        yield "Weekend";
    }
};
System.out.println(typeOfDay);
// 输出:
// It's the weekend!
// Weekend

yield 关键字

yield 用于在 switch 表达式的代码块中返回一个值,它类似于 return,但只作用于 switch 表达式内部,使用 yield 可以确保每个 case 都有明确的返回值,从而避免“贯穿”。

多常量标签

在传统的 switch 语句中,如果想为多个 case 执行相同的操作,需要重复写 case 标签或利用“贯穿”。switch 表达式简化了这一点,可以用逗号 将多个常量放在同一个 case 中。

// 上面的例子已经展示了这一点
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Weekday";

default

default 标签和 case 标签的用法完全一样,可以返回一个值。

int errorCode = 404;
String errorMessage = switch (errorCode) {
    case 200 -> "OK";
    case 404 -> "Not Found";
    case 500 -> "Internal Server Error";
    default -> {
        System.out.println("Unknown error code: " + errorCode);
        yield "Unknown Error";
    }
};

switch 表达式 vs. switch 语句(传统)

特性 switch 表达式 (Java 12+) switch 语句 (Java 11及以前)
目的 计算并返回一个值 执行一个操作块
返回值 可以,通过赋值给变量 不可以,没有返回值
语法 使用 -> 只能使用
break 不需要,也不允许(在 -> 语法中) 必须,否则会“贯穿”
yield 在代码块中用于返回值 不存在
多常量 支持,用逗号分隔 支持,但需要重复写 case 或利用“贯穿”
典型用法 String result = switch (...) { ... }; switch (...) { ... }

完整示例与最佳实践

假设我们要根据成绩等级计算绩点。

public class SwitchExpressionBestPractice {
    public static void main(String[] args) {
        char grade = 'B';
        // 使用 switch 表达式
        double gpa = switch (grade) {
            case 'A' -> 4.0;
            case 'B' -> 3.0;
            case 'C' -> 2.0;
            case 'D' -> 1.0;
            case 'F' -> 0.0;
            default -> {
                // 处理无效输入
                System.err.println("Invalid grade: " + grade);
                yield -1.0; // 返回一个错误码
            }
        };
        if (gpa >= 0) {
            System.out.println("The GPA for grade " + grade + " is " + gpa);
        } else {
            System.out.println("Could not calculate GPA.");
        }
        // 输出: The GPA for grade B is 3.0
    }
}

switch 表达式是 Java 语言的一次重要进化,它使得代码更加:

  1. 简洁:用一行代码就能完成条件判断和赋值。
  2. 安全:从语法层面杜绝了“贯穿”这一经典错误。
  3. 强大switch 不再仅仅是流程控制语句,更是一个功能完备的表达式,可以无缝集成到任何需要表达式的地方。

建议:从 Java 12 开始,只要条件允许,优先使用 switch 表达式,而不是传统的 switch 语句,只有在需要执行复杂的、没有返回值的操作序列时,才考虑使用传统的 switch 语句。

分享:
扫描分享到社交APP
上一篇
下一篇