经过jdk19第一次预览,jdk20第二次预览,jdk21成为正式版api,对jdk16的record类型和instanceof进行了加强,使匹配不仅限于普通类,还扩展到了record类型,并且支持到record类型的参数,可以直接解析构造参数,并且可以使用var推断类型,还支持record的嵌套;由于jdk21对switch匹配模式也进行了增强,所以record也可以匹配switch语句;
demo:
可以直接解析属性,支持var推断:
@Test
void test() {
record Cat(String name, String color, int age) {}
Object obj = new Cat("tom", "blue", 12);
if (obj instanceof Cat cat) { // 之前jdk16可匹配直接转类型
System.out.println(cat);
}
if (obj instanceof Cat(String name, var color, var age)) { // jdk21,可直接解析属性,并支持var推断
System.out.println(name);
System.out.println(color);
System.out.println(age);
}
}

可以解析record的嵌套,使代码更简单:
@Test
void test2() {
record Student(String stuName, int stuAge) {}
record School(String schName, String schNo) {}
record Info(Student stu, School sch) {} // record嵌套record
Object obj = new Info(new Student("Jerry", 10), new School("HELLO_SCHOOL", "10001"));
if (obj instanceof Info(Student(String stuN, int stuA), School school)) { // 可直接解析record嵌套
System.out.println(stuN);
System.out.println(stuA);
System.out.println(school);
}
}

使用var类型推断也支持泛型:
@Test
void test3() {
record A<T>(T t) {}
A<String> x = new A<>("a");
if (x instanceof A(var param)) {
System.out.println(param.getClass());
}
A<Integer> y = new A<>(123);
if (y instanceof A(var param)) {
System.out.println(param.getClass());
}
A<A<Long>> z = new A<>(new A<Long>(100L));
if (z instanceof A(A(var param))) {
System.out.println("%s:%s".formatted(param, param.getClass()));
}
}

由于switch的表达式和模式匹配必须有穷尽,所以使用swtich和record组合的时候,要么穷尽所有可能的case,要么最后追加个default终结穷尽:
准备三个类:
class P{}
class C1 extends P{}
class C2 extends P{}
@Test
void test4() {
record A<T>(T arg) {}
A<P> obja = new A<P>(new C2());
switch (obja) {
case A<P>(C1 x) -> System.out.println("c1");
case A<P>(C2 y) -> System.out.println("c2");
case A<P>(P z) -> System.out.println("p");
}
}

如果注释掉最后一个case就会报错:(穷举未覆盖P类型)

注释掉前两个不会报错,因为最后一个case A<P>(P z)已经包含了C1和C2了;
此外还要主要case的顺序,条件范围要从窄到宽,避免前面的条件覆盖了后面的条件导致后面的条件永远case不到;


被折叠的 条评论
为什么被折叠?



