0%

Java语言新特性漫谈:Java 12之switch

本文是《Java语言新特性漫谈》系列文章中的一篇,该系列文章主要探讨各 Java 版本的语言特性方面的增强更新。

改进的 switch

Java 12 改进了 switch 语句。主要涉及两点:

  1. 新的 case 标签
  2. switch 表达式

比如,返回指定星期几的英文字母数的程序,在 Java 12 之前可能是下面这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public enum Day { SUNDAY, MONDAY, TUESDAY,
WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; }

int numLetters = 0;
Day day = Day.WEDNESDAY;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
break;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new IllegalStateException("Invalid day: " + day);
}
System.out.println(numLetters);

上面的程序至少有两点会导致编程人员的不适:
首先,switch 语句不能用于给变量赋值,因此需要有一个外部变量来存储返回值;
其次,总是不经意间被遗忘的 break,可能引起意外的“贯穿”(fall through)。

在 Java 12 中,可以简化成这样:

1
2
3
4
5
6
7
var numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("Invalid day: " + day);
};

可以看到这里使用了新的 case 标签写法,使得 case 子句更为简洁紧凑了。

再一点,switch 不再仅仅是语句,也可以做为表达式为变量赋值了。

当然,要作为表达式赋值,必然需要有返回值,如果 case 子句未包含返回语句,将导致错误。

小结

  • 除了老式的 colon case 语法外,引入了新的 arrow case 语法。如下:
1
case label_1, label_2, ..., label_n -> expression;|throw-statement;|block 
  • 与 colon case 语法相比,arrow case 不存在“贯穿”行为。
  • 如果箭头右边是一个表达式,那么这个表达式的值就是 switch 表达式的值。

什么是预览特性?

注意,上面提到的特性在 Java 12 中都是“预览特性”!

预览特性,是一个新特性,它的设计、规范和实现都是完整的,但它不是永久性的,这意味着该特性可能以不同的形式存在,或者在未来的JDK版本中根本不存在。

事实上,上文中的确还有一点 switch 的新特性没有提到,因为它在后续版本中移除了。

是什么呢?它就是 switch 表达式用以返回值的语句。

细心的读者已经意识到一个问题,带箭头的新 case 标签只有在右侧是表达式的时候才有返回值。那如果右侧是一个由多个语句组成的块,如何返回值?

答案是,使用 break 语句!

Java 12 扩展了 break 的能力,让它可以 break xxx; 的形式为 switch 语句提供返回值。

纳尼!笔者看到这个特性的第一反应是:不会与 break label 的语义混淆吗?
准确地说,应该会引入一定的“阅读障碍”,因为两者的语义只能基于上下文来区分。
so…话说它不是被干掉了嘛!

But,后续版本移除了这个特性,将这项任务交给了 yield

最后,也是最重要的,预览特性是需要手动启用的:

1
2
javac --enable-preview --release 12 MyApp.java
java --enable-preview MyApp

参考

JEP 325: Switch Expressions (Preview)

Java Language Udpates: Java 12