Switch表达式
Java14
提供了新的switch语法,即:
switch的分支结果可以直接作为返回结果给到前面的变量,或是在后续课程中用做方法返回值使用:
int score = 9;
//直接让res接收switch的结果
char res = switch(score){
case 10,9 -> 'A';
case 8 -> 'B';
case 7,6 -> 'C';
default -> 'D';
}; //注意这是一个赋值语句,后面要加分号
sout(res);
即switch有了返回值,变量需要接收,switch语句中的冒号,break等也不在了,取而代之的是箭头。
当然,如果除了返回值外,还需要执行别的操作,可以写成代码块的形式,此时要用到关键字 yield,表示延迟返回:
int score = 9;
char res = switch(score){
case 10,9 -> 'A';
case 8 -> 'B';
case 7,6 -> 'C';
default -> {
sout("不及格");
yield 'D'; //指定延迟返回的结果,并自动结束分支
};
sout(res);
switch模式匹配(Java21后)
即switch除了可以根据变量的不同值做出判断外,增加了一个新功能:判断变量类型(只能是引用类型,Java25之后可以是基本类型)
public static void tellInstance(Object obj){
String type = switch (obj){
case Integer i -> "Integer"; //i和s为定义的返回值的变量名
case String s -> "String";
case null -> "Null"; //null和default直接加箭头
default -> "Other";
}; //记得每个语句和最后加分号
System.out.println(type);
}
我们注意到,模式匹配中的类型后面必须跟一个变量名字,能否有一种办法省略掉呢?在Java 22之后,我们可以使用_下划线来直接取代,表示这是一个后续不会使用的未命名的变量
如果除了判断类型,我们还想判断别的,可以使用 when 关键字,在后面加上想要额外判断的条件进行额外条件检查,这种操作称为”守卫条件”
when后面需要填写判断条件,和if一样,必须为一个返回值为boolean的表达式,也可以使用与或非操作
这样,在switch中也可以实现区间判断:
public static void tellGrade(Integer score){
String type = switch(score){
case Integer i when score >= 90 -> "A";
case Integer i when score >= 80 -> "B";
case Integer i when score >= 60 -> "C";
default -> "D";
};
System.out.println(type);
}
记录类型
此外,针对于此前提到的记录类型,在switch语句中支持直接解构使用:
record Point(int x, int y) {}
public static Integer test(Object object) {
return switch (object) {
case Point(int x, int y) -> x + y; //直接解构其参数使用
case String _ -> 10;
default -> 5;
};
}
这里针对于记录类型,类似重新写了一次类型声明,编写完整的类名加参数Point(int x, int y)表示当object如果是记录类型,则进入此分支且解构其内部成员变量,这里写的x和y作为结构出来的变量可以直接在后续使用。同样的,解构的变量如果后续不使用也可以直接使用下划线代替。
return switch (object) {
case Point(int _, int y) -> y;
case String _ -> 10;
default -> 5;
};
switch还支持对记录类内部成员的类型嵌套匹配:
record Container(Object data) {} //这里data是Object类型的
public static Integer test(Container object) {
return switch (object) {
case Container(String str) -> str.length(); //其内部类型如果是String
case Container(Integer i) -> i; //其内部类型如果是Integer
default -> 0;
};
}