Java 新特性解析:模式匹配

Java SE 14(于 2020 年 3 月发布)引入了一种模式匹配作为预览特性,将成为Java SE 16(将于 2021 年 3 月发布)的一项永久性特性。

模式匹配的第一阶段仅限于一种模式(类型模式)和一种语言构造(instanceof),但这只是整个完整特性的第一部分。

简单地说,模式匹配可以帮我们减少繁琐的条件状态提取。在进行条件状态提取时,我们问一个与某个对象有关的问题(比如“你是 Foo 吗”),如果答案是肯定的,我们就从对象中提取状态:“if (x instanceof Integer i) { … }”,其中 i 是绑定变量。

使用 instanceof 获取对象类型是一种条件提取形式,在获得到对象类型之后,总是要将对象强制转换为该类型。

我们可以在 java.util.EnumMap 的复制构造函数中看到一个典型的例子:

public EnumMap(Map m) {
   
    if (m instanceof EnumMap) {
   
        EnumMap em = (EnumMap) m;
        // optimized copy of map state from em
    } else {
   
        // insert elements one by one
    }
}

构造函数接收另一个 Map 作为参数,它可能是也可能不是一个 EnumMap。如果是的话,构造函数可以将其强制转换为 EnumMap,并使用更有效的方法复制 Map 的状态,否则的话,它将使用一般的插入方式。

这种“测试并进行强制转换”的习惯用法是多余的吗?在有了 m instanceof EnumMap 之后,我们还可以做些什么?模式匹配可以将测试和强制转换合并到单个操作中。类型模式将类型名称与绑定变量的声明组合在一起,如果 instanceof 成功,绑定变量将被绑定到对象的窄化类型:

public EnumMap(Map m) {
   
    if (m instanceof EnumMap em) {
   
        // optimized copy of map state from em
    } else {
   
        // insert elements one by one
    }
}

在上面的例子中,EnumMap em 是一种类型模式(看起来像是一种变量声明)。我们扩展了 instanceof,让它可以接受模式和普通类型。我们先测试 m 是不是一个 EnumMap,如果是,则将其转换为 EnumMap,并将结果绑定到 if 语句第一行中的 em 变量。

在 instanceof 之后必须进行显式的类型转换,这是一种繁琐的操作,而融合这些操作的好处不仅仅是为了简洁(尽管简洁是美好的),它还消除了一个常见的错误来源。在剪切和粘贴 instanceof 及强制转换代码,容易在修改了 instanceof 的类型之后忘记修改强制转换类型,这就给了漏洞一个藏身之处。通过消除这个问题,我们可以消灭所有这种类型的 bug。

另一个需要经常进行“测试后强制转换”的地方是在实现 Object::equals 时。IDE 可能会为 Point 类生成 equals()方法:

public boolean equals(Object o) {
   
    if (!(o instanceof Point))
        return false;
    Point p = (Point) o;
    return x == p.x && y == p.y;
}

下面是使用模式匹配的等效代码:

public boolean equals(Object o) 

你可能感兴趣的:(Java技术,编程程序,IT行业)