为什么空值与记录模式匹配?

问题描述 投票:0回答:1

我一直在尝试 Java 21 中的模式匹配与记录模式的示例。官方文档断言空值不匹配任何记录模式。不过,我尝试这个例子:

record Point(Integer x, Integer y) {}

public class MainPatternMatchingRecord {
    public static void main(String[] args) {
        printSum(new Point(null, 2));
    }

    private static void printSum(Object obj) {
        if (obj instanceof Point(var x, var y)) {
            System.out.println(x + 1);
        }
    }
}

这里,根据我对 JEP 的理解, new Point(null, 2) 不应该匹配 instanceof Point(var x, var y) 但是当运行程序时,会抛出这个异常:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "x" is null

为什么会出现这种行为?应该如何正确解释空值与任何记录模式不匹配?

java pattern-matching record-patterns
1个回答
0
投票

JEP 440确实说:

空值与任何记录模式都不匹配。

但是仔细看看记录模式是什么:

记录模式由记录类类型和(可能为空)模式列表组成[...]

JEP 还指定了如下记录模式的语法:

Pattern:
  TypePattern
  RecordPattern

TypePattern:
  LocalVariableDeclaration

RecordPattern:
  ReferenceType ( [ PatternList ] )

PatternList : 
  Pattern { , Pattern }

通过这些定义,我们可以看到

var x
var y
不是记录模式。它们是类型模式。 “空值与任何记录模式都不匹配”的规则在这里不适用。

我无法准确找到 JEP 中说记录模式中的类型模式的行为是这样的,但 预览规范 确实明确指出了这一点:

考虑一下,例如:

class Super {}
class Sub extends Super {}
record R(Super s) {}

我们期望

R
类型的所有非空值都与模式匹配
R(Super s)
,包括评估结果的值 表情
new R(null)
。 (即使空值不匹配 模式
Super s
。)但是,我们不希望该值与模式
R(Sub s)
匹配,因为记录组件的
null
值与模式
Sub s
不匹配。


这是另一个例子:

record Foo(Integer x, Integer y) {}

record Bar(Foo a, Foo b) {}
private static void printSum(Object obj) {
    if (obj instanceof Bar(Foo(Integer x1, Integer y1), Foo(var x2, var y2))) {
        System.out.println("matched!");
    }
}

现在,

new Bar(null, null)
匹配模式
Bar(Foo(Integer x1, Integer y1), Foo(var x2, var y2))
,因为
Foo(Integer x1, Integer y1)
是一个记录模式,而
null
与它不匹配。

© www.soinside.com 2019 - 2024. All rights reserved.