在Java的模式匹配实例中,使用了一个额外的标识符来缩小类型:

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

为什么这是必要的?The JEP似乎不能证明这一点,但我相信这是有原因的.以下内容有什么不可取之处?

Object o = "test";
if (o instanceof String) {
    System.out.println(o.length());
}

TypeScriptKotlin在没有其他标识符的情况下执行类似的操作.

我猜这是一个向后兼容的问题-Java的怪癖通常是-但我想不出一个例子来证明这一点.

我唯一能想到的是,可能有人编写了与第二个示例pre-pattern matching类似的东西,并依赖它进行not次编译,但这似乎是一个很弱的理由.

推荐答案

如果Java引入了类似"智能instanceof"的东西,我们可以说这个特性可以在不引入新变量的情况下工作.

但这并不是我们所介绍的.新特性是Pattern Matching,这是一个更大的概念,尽管在第一步中仅以最简单的形式实现.这也是一种新的集成方法,而不是几十年来一直致力于大功能,更小的功能不断添加到Java中,同时保持了大的愿景.

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

(给定)

record Point(int x, int y) {}
void printSum(Object o) {
    if (o instanceof Point(int x, int y)) {
        System.out.println(x+y);
    }
}

甚至

(给定)

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

由于Pattern Matching包括创建(有时是多个)新变量,因此仅创建一个新变量并包含与已存在变量相同的引用的情况只是一种极端情况.

if(foo.getObject() instanceof List<?> l && l.get(0) instanceof Map<?,?> m
   && m.get("foo") instanceof String s) {
       // use s
}

还值得注意的是,模式变量的范围为is complex.如果变量也存在于这个范围之外,但具有不同的类型,则会更加混乱.

因此,在instanceof存在的情况下改变变量的类型虽然很诱人,但会导致问题(一些 comments 还提到了方法重载 Select ),同时,也不符合Java语言开发人员的实际愿景.

Java相关问答推荐

无法从TemporalAccessor获取Instant:{},ISO解析为2024-04- 25 T14:32:42类型为java.time. form.Parsed

Java 8 RDX-如何设置单个选项卡标题文本的 colored颜色

Spring安全实现多个SQL表身份验证

同时运行JUnit测试和Selenium/Cucumber测试时出现问题

如何粘合(合并)文件Lucene?

对运行在GraalVM-21上的JavaFX应用程序使用分代ZGC会警告不支持JVMCI,为什么?

在bash中将数组作为Java程序的参数传递

在springboot 3中,当我调用api endpoint时,会出现404

测试容器无法加载类路径初始化脚本

每次FXMLLoader调用ApplationConext.getBean(类)时创建@Component的新实例

如何从日志(log)行中删除包名称?

错误:不兼容的类型:Double不能转换为Float

FETCH类型设置为LAZY,但它仍会发送第二个请求

在Spring Boot JPA for MySQL中为我的所有类创建Bean时出错?

在一行中检索字符分隔字符串的第n个值

有没有办法知道在合并中执行了什么操作?

如何在ApacheHttpClient 5中为单个请求设置代理?

当使用不同的参数类型调用时,为什么围绕Objects.equals的类型安全包装不会失败?

始终使用Spring Boot连接mongodb上的测试数据库

人们在 IntelliJ 上将-Dhttp.proxyHost=your.proxy.net -Dhttp.proxyPort=8080放在哪里?