为什么 instanceof 模式匹配需要标识符?

Mic*_*ael 2 java java-16

在Java的instanceof模式匹配中,使用附加标识符来缩小类型:

Object o = "test";
if (o instanceof String s) {
    System.out.println(s.length()); // s is of type String
}
Run Code Online (Sandbox Code Playgroud)

为什么有必要?JEP似乎没有证明其合理性,但我确信这是有原因的。以下有什么不好的地方?

Object o = "test";
if (o instanceof String) {
    System.out.println(o.length());
}
Run Code Online (Sandbox Code Playgroud)

TypeScriptKotlin可以做类似的事情,而无需另一个标识符。

我猜这是一个向后兼容性的问题——Java 的怪癖通常是这样——但我想不出一个可以证明这一点的例子。

我唯一能想到的是,有人可能编写了类似于第二个示例预模式匹配的内容,并依赖它来编译,但这似乎是一个薄弱的理由。

Hol*_*ger 7

如果 Java 引入了类似 \xe2\x80\x9csmart instanceof\xe2\x80\x9d 的东西,我们可以说这个功能可以在不引入新变量的情况下工作。

\n

但那个\xe2\x80\x99并不是所介绍的。新功能是模式匹配,这是一个更大的概念,尽管第一步只是以最简单的形式实现。这也是一种新的集成方法,不是在大功能上花费数十年的时间,而是在保持大愿景的同时不断将较小的功能添加到Java中。

\n

JDK-8260244描述了接下来的步骤之一,这将允许类似的事情

\n

(给定)

\n
record Point(int x, int y) {}\n
Run Code Online (Sandbox Code Playgroud)\n
void printSum(Object o) {\n    if (o instanceof Point(int x, int y)) {\n        System.out.println(x+y);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

甚至

\n

(给定)

\n
record Point(int x, int y) {}\nenum Color { RED, GREEN, BLUE }\nrecord ColoredPoint(Point p, Color c) {}\nrecord Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}\n
Run Code Online (Sandbox Code Playgroud)\n
static void printXCoordOfUpperLeftPointWithPatterns(Rectangle r) {\n    if (r instanceof Rectangle(ColoredPoint(Point(var x, var y), var c), var lr)) {\n        System.out.println("Upper-left corner: " + x);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

由于模式匹配包括创建(有时是多个)新变量,因此仅创建一个包含与现有变量相同引用的新变量的情况只是一种特殊情况。\n即使到目前为止已实现的情况,也涵盖了更多的情况那。例如

\n
if(foo.getObject() instanceof List<?> l && l.get(0) instanceof Map<?,?> m\n   && m.get("foo") instanceof String s) {\n       // use s\n}\n
Run Code Online (Sandbox Code Playgroud)\n

还值得注意的是,模式变量的范围很复杂。如果变量也存在于该范围之外,但类型不同,那就更令人困惑了。

\n

因此,在 存在的情况下根据上下文更改变量的类型instanceof虽然很诱人,但会导致问题(一些评论还提到了方法重载选择),同时,不会\xe2\x80\x99 适合的实际愿景Java 语言开发人员。

\n