本文是《Java语言新特性漫谈》系列文章中的一篇,该系列文章主要探讨各 Java 版本的语言特性方面的增强更新。
改进的 switch
Java 12 改进了 switch
语句。主要涉及两点:
- 新的
case
标签 switch
表达式
比如,返回指定星期几的英文字母数的程序,在 Java 12 之前可能是下面这样的:
1 | public enum Day { SUNDAY, MONDAY, TUESDAY, |
上面的程序至少有两点会导致编程人员的不适:
首先,switch
语句不能用于给变量赋值,因此需要有一个外部变量来存储返回值;
其次,总是不经意间被遗忘的 break
,可能引起意外的“贯穿”(fall through)。
在 Java 12 中,可以简化成这样:
1 | var numLetters = switch (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 | javac --enable-preview --release 12 MyApp.java |