概述
我们可能会经常使用switch
语句来实现从一个值到另一个值的转换。在早期版本的Java中,这需要我们将switch
语句嵌入到一个单独的函数中,并使用每个case
中的return
语句,或者需要在每个case
中将值赋给一个临时变量,以便在函数的后续部分中使用。
从Java 14开始,switch
表达式中的yield
关键字为我们提供了一种更好的实现方式。
yield关键字
yield
关键字允许我们通过返回一个值来退出switch
表达式,该值将成为switch
表达式的值。
这意味着我们可以将switch
表达式的值赋给一个变量。
语法:
yield Expression ;
yield
语句通过使封闭的switch
表达式产生一个指定的值来转移控制。yield
语句尝试将控制权转移给最内层的封闭switch
表达式;这个被称为“yield目标”的封闭表达式随后立即正常完成,并且Expression
的值就成为了switch
表达式的值。- 如果一个 yield 语句没有 yield 目标,那么这是一个编译时错误。
- 如果一个yield语句的表达式为
void
,那么这是一个编译时错误。
使用带箭头操作符的yield
package com.test.pkg1;
public class Test {
enum WeekDay {
MONDYA, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, STATURDAY, SUNDAY;
}
public static void main(String[] args) {
int result = calculate(WeekDay.MONDYA);
System.out.println(result);
result = calculate(WeekDay.WEDNESDAY);
System.out.println(result);
result = calculate(WeekDay.THURSDAY);
System.out.println(result);
}
public static int calculate(WeekDay d) {
return switch (d) {
case MONDYA, TUESDAY -> {
System.out.println(1);
yield 1;
}
case WEDNESDAY -> {
System.out.println(2);
yield 2;
}
default -> {
System.out.println(3);
yield 3;
}
};
}
}
输出:
1
1
2
2
3
3
使用冒号分隔符的yield
package com.test.pkg1;
public class Test {
enum WeekDay {
MONDYA, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, STATURDAY, SUNDAY;
}
public static void main(String[] args) {
int result = calculate(WeekDay.MONDYA);
System.out.println(result);
result = calculate(WeekDay.WEDNESDAY);
System.out.println(result);
result = calculate(WeekDay.THURSDAY);
System.out.println(result);
}
public static int calculate(WeekDay d) {
return switch (d) {
case MONDYA:
case TUESDAY:
System.out.println(1);
yield 1;
case WEDNESDAY:
System.out.println(2);
yield 2;
default:
System.out.println(3);
yield 3;
};
}
}
输出:
1
1
2
2
3
3
这段代码的行为与前一部分相同。但箭头操作符更清晰,也更不容易出现忘记yield(或break)语句的情况。
需要注意的是,我们不能在同一switch表达式中混合使用冒号和箭头这两种分隔符。
完备性
使用switch
表达式和yield
的另一个好处是,如果缺少case
覆盖,我们会看到一个编译错误。让我们从使用箭头操作符的switch
表达式中移除default case
来验证一下:
return switch (d) {
case MONDYA, TUESDAY -> {
System.out.println(1);
yield 1;
}
case WEDNESDAY -> {
System.out.println(2);
yield 2;
}
};
上面的写法会给出编译错误提示:A Switch expression should cover all possible values
我们可以将default case加回来,或者我们可以具体地覆盖d
的所有可能值:
package com.test.pkg1;
public class Test {
enum WeekDay {
MONDYA, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, STATURDAY, SUNDAY;
}
public static void main(String[] args) {
int result = calculate(WeekDay.MONDYA);
System.out.println(result);
result = calculate(WeekDay.WEDNESDAY);
System.out.println(result);
result = calculate(WeekDay.THURSDAY);
System.out.println(result);
}
public static int calculate(WeekDay d) {
return switch (d) {
case MONDYA, TUESDAY -> {
System.out.println(1);
yield 1;
}
case WEDNESDAY -> {
System.out.println(2);
yield 2;
}
case THURSDAY, FRIDAY, STATURDAY, SUNDAY -> {
System.out.println(3);
yield 3;
}
};
}
}