如果值v与记录模式Point(int i, int j)匹配,则它是记录类型Point的实例;如这样,模式变量i将被初始化为在值v上调用与i对应的访问器方法的结果,模式变量j将被初始化为在值v上调用与j对应的访问器方法的结果。(模式变量的名称不需要与记录组件的名称相同;也就是说,记录模式Point(int x, int y)的行为相同,只是模式变量x和y被初始化。)
null值不与任何记录模式匹配。
记录模式可用var来匹配记录组件,而无需声明组件的类型。在这种情况下,编译器会推断由var模式引入的模式变量的类型。如模式Point(var a, var b)是模式Point(int a, int b)的简写。
记录模式声明的模式变量集合包括模式列表中声明的所有模式变量。
如果一个表达式可以在不需要未经检查的转换的情况下将其转换为模式中的记录类型,则该表达式与记录模式兼容。
如果记录模式命名了一个泛型记录类,但没有给出类型参数(即,记录模式使用原始类型),则始终会推断类型参数。例如:
JEP 441增强了switch表达式和switch语句,以支持模式标签。无论是switch表达式还是模式switch语句,都必须是完整的:switch块必须有处理选择器表达式的所有可能值的子句。对于模式标签,这是通过分析模式的类型来确定的;例如,case标签case Bar b匹配类型为Bar及其所有可能的子类型的值。
对于涉及记录模式的模式标签,分析更加复杂,因为我们必须考虑组件模式的类型,并对密封层次结构进行调整。例如,考虑以下声明:
class A {}
class B extends A {}
sealed interface I permits C, D {}
final class C implements I {}
final class D implements I {}
record Pair<T>(T x, T y) {}
Pair<A> p1;
Pair<I> p2;
复制代码
以下switch不是完整的,因为没有匹配包含两个类型为A的值的对:
// Java 21及以后
switch (p1) { // 错误!
case Pair<A>(A a, B b) -> ...
case Pair<A>(B b, A a) -> ...
}
复制代码
这两个switch是完整的,因为接口I是密封的,因此类型C和D涵盖了所有可能的实例:
// Java 21及以后
switch (p2) {
case Pair<I>(I i, C c) -> ...
case Pair<I>(I i, D d) -> ...
}
switch (p2) {
case Pair<I>(C c, I i) -> ...
case Pair<I>(D d, C c) -> ...
case Pair<I>(D d1, D d2) -> ...
}
复制代码
相比之下,这个switch不是完整的,因为没有匹配包含两个类型为D的值的对:
// Java 21及以后
switch (p2) { // 错误!
case Pair<I>(C fst, D snd) -> ...
case Pair<I>(D fst, C snd) -> ...
case Pair<I>(I fst, C snd) -> ...
}
复制代码
10 未来
记录模式的描述中提到了许多可以扩展这里描述的记录模式的方向:
可变参数模式,用于可变数量的记录
匿名模式,可以出现在记录模式的模式列表中,匹配任何值,但不声明模式变量
适用于任意类的值而不仅仅是记录类的模式。
我们可以在未来的JEP中考虑其中的一些方向。
11 依赖关系
本JEP建立在Pattern Matching for instanceof(JEP 394)的基础上,该功能已在JDK 16中发布。它与Pattern Matching for switch(JEP 441)共同演进。