类型匹配
在 JDK 14 中以预览版的形式发布。在 JDK 15 中,改进的类型匹配再次以预览版的形式发布。最后,类型匹配在 JDK 16 正式发布。
类型匹配主要是用于优化instanceof强制类型转换的情况。
语法
对象值 instanceof 对象类型 比对成功赋值给的对象
以前写法:
public BmwCar bmwCar(Car car){
if (car instanceof BmwCar) {
return (BmwCar) car;
}
return null;
}
类型匹配写法:
public BmwCar bmwCar2(Car car){
if (car instanceof BmwCar bmwCar) {
return bmwCar;
}
return null;
}
这样写的优点: 可以简化我们类型强转可能会带来的错误,由内部判断,如果属于,则自动将后面的值转换为匹配类型。
作用域
- 1. 匹配情况
if (car instanceof BmwCar bmwCar) {
// bmwCar能使用的范围
}
// bmwCar不能使用
- 1. 不匹配情况
- • 只有
if
的情况:
if (!(car instanceof BmwCar bmwCar)) {
// bmwCar不能使用
}
// bmwCar能使用的范围
- • 有
if(){}else(){}
的情况
if (!(car instanceof BmwCar bmwCar)) {
// bmwCar不能使用
} else {
// bmwCar能使用的范围
}
// bmwCar能使用的范围
- 1. 逻辑运算符
- •
&&
情况,可以直接使用再&&
后面用于判断
if (car instanceof BmwCar bmwCar && bmwCar.tire() == "米其林"){}
- •
||
情况,不可以使用在||
后面
- • 因为
||
只要前面不满足就没必要使用转换后的值进行判断(类型不匹配转换肯定不成功) - • 前面满足就是true,那么也不会去判断后面
优点
- • 降低我们类型匹配后再强转的出错率
- • 提高了代码转换的效率
Switch 表达式
在 JDK 12 中以预览版的形式发布。在 JDK 13 中,改进的 switch 表达式再次以预览版的形式发布。最后,switch 表达式在 JDK 14 正式发布。
Switch表达式
以前写法:
public String switchDemo(Integer state) {
String desc;
switch (state) {
case 1:
case 2:
case 3:
desc = "进入1,2,3语句";
break;
case 4:
desc = "4语句";
break;
case 5:
case 6:
if (state % 2 == 0) {
desc = "进入5,6语句且不能被2整除";
} else {
desc = "进入5,6语句且能被2整除";
}
break;
default:
throw new IllegalStateException();
}
return desc;
}
优化写法:
public String switchDemo(Integer state) {
return switch (state) {
case 1, 2, 3 -> "进入1,2,3语句";
case 4 -> "4语句";
case 5, 6 -> {
if (state % 2 == 0) {
yield "进入5,6语句且不能被2整除";
} else {
yield "进入5,6语句且能被2整除";
}
}
default -> throw new IllegalStateException();
};
}
变动情况:
- • 和之前的switch语句不同,这个switch是一个表达式(有返回值)
- • 一个case语句后面可以跟多个匹配项
- • 标识符由
:
变为->
- • 箭头右侧的值表示表达式匹配的情况下,switch表达式的值
- • 箭头右侧是代码块的情况,由yield关键字指明switch表达式的值
注意:
- • yield关键字只能使用在switch表达式的代码块中,如果不是代码块直接返回会报错
// 编译会报错
case 4 -> yield "4语句"; - • switch 表达式里,必须要将所有情况列举出来,不能多、也不能少
public String switchDemo(Integer state) {
return switch (state) {
case 1, 2, 3 -> "进入1,2,3语句";
case 4 -> "4语句";
case 5, 6 -> {
if (state % 2 == 0) {
yield "进入5,6语句且不能被2整除";
} else {
yield "进入5,6语句且能被2整除";
}
}
// 如果注释了default那么编译就会报错
// default -> throw new IllegalStateException();
};
} - • 不能在case语句块中使用return、break
case 5, 6 -> {
if (state % 2 == 0) {
// 会报错
//return;
break;
}
yield "进入5,6语句且能被2整除";
}
Switch 语句
和表达式一样也做了对应的改进
public void switchDemo2(Integer state) {
switch (state) {
case 1, 2, 3 -> System.out.println("进入1,2,3语句");
case 4 -> System.out.println("4语句");
case 5, 6 -> {
if (state % 2 == 0) {
System.out.println("进入5,6语句且不能被2整除");
break;
}
System.out.println("进入5,6语句且能被2整除");
}
default -> throw new IllegalStateException();
}
}
与Switch表达式不同点:
- • 语句块里面不能使用yield
- • 可以在case后面语句块中使用return、break关键字
- • 可以不用列出所有情况,比如上面将default注释了也没问题
switch匹配(特性未定稿)
switch 的模式匹配这个特性,在 JDK 17 中以预览版的形式发布。
JDK 17 之前的 switch 关键字可以匹配的数据类型包括数字、枚举和字符串。switch匹配用于匹配对象(引用数据类型)。
如下:
public static boolean isFileStream(InputStream in){
return switch (in) {
case FileInputStream f-> true;
case ByteArrayInputStream b-> false;
case null,default -> false;
};
}
特点:
- • 支持 null 匹配
- • 不会像之前传入null会报空指针异常
- •
case
后面的对象类型后面跟着一个定义(如:FileInputStream f
中的f
),这个是匹配后转换的数据类型,在->
后面可以使用f.fun()
来使用对应的方法 - •
case
必须包含全部的业务场景,如果囊括不完的也要使用default
表示,否则编译会报错 - • 改进后的switch(包括 switch 语句和 switch 表达式),比if(){}else(){}的性能更好
注意:
public static boolean isFileStream(InputStream in){
return switch (in) {
case FileInputStream f-> true;
case ByteArrayInputStream b-> false;
// 由于上面的case已经返回false,而且下面的case已经包含了上面的,所以下面的情况会报错
// case ByteArrayInputStream b && 1 == 1-> false;
case null,default -> false;
};
}