详解 Java 17 中的模式匹配(Pattern Matching)

提到模式匹配(Pattern Matching),Java 开发人员可能会比较陌生。实际上,其他编程语言的开发人员早就已经使用过模式匹配了。JVM 上的编程语言 Scala 的模式匹配功能就很强大。

什么是模式匹配?

为了更好地解释模式匹配,我们从一个简单的例子开始。我们希望创建一个方法,可以把任何对象转换成 String 格式。这就需要根据对象的类型来进行不同的格式化操作。我们可以很容易就写出下面这样的代码。这段代码的核心是使用 instanceof 操作符来检查输入对象的类型,再根据对象类型进行格式化操作。

public class ObjectFormatter {public String format(Object input) {if (input == null) {return “”;} else if (input instanceof Number) {return NumberFormat.getNumberInstance().format(input);} else if (input instanceof LocalDateTime) {return ((LocalDateTime) input).format(DateTimeFormatter.ISO_DATE_TIME);} else {return input.toString();}}}

上述对 instanceof 操作符的使用就是模式匹配的一种简单形式。

一个模式由匹配 predicate 和模式变量的集合组成。

  • 匹配 predicate 判断一个模式是否可以匹配目标对象。
  • 如果模式匹配的话,模式变量的集合用来从目标对象中提取值。

在 instanceof 操作符的例子中,匹配 predicate 的作用是检查目标对象的类型,而模式变量的集合中只有一个变量,就是目标对象自身。这种类型的模式,被称为类型模式(type pattern)。除了类型模式之外,计划中的模式还包括记录类型模式和数组模式。

模式匹配是一个涵盖范围非常大的功能。根据现在 Java 的发布周期,模式匹配的内容会在不同的 Java 版本中逐渐添加进来。具体的发布周期可以参考下面的表格。这个表格的右侧三列表示的是不同的与模式匹配相关的功能,每一行表示这些功能在对应 Java 版本中的可用状态。

Java版本

instanceof 模式

switch 的模式匹配

记录类型模式

Java 14

预览

Java 15

二次预览

Java 16

正式功能

Java 17

正式功能

预览

Java 18

正式功能

二次预览

Java 19

正式功能

三次预览

预览

以 Java 17 为例,可以使用 instance 模式的正式功能,以及 switch 模式匹配的预览功能。

Java 18 和 Java 19 中可用的模式匹配功能也列在了表格中,作为参考。

instanceof 模式匹配

Java 中的 instanceof 操作符用来检查对象的类型。下面的代码给出了通常使用 instanceof 操作符的代码范式。在 if 语句中使用 instanceof 来进行检查,如果检查通过,则使用强制类型转换,把输入对象 obj 转换成 String 类型的 s,最后再使用变量 s。

if (obj instanceof String) {String s = (String) obj;}

从上述代码中可以看到,对 instanceof 操作符的使用范式是非常繁琐的,其中需要检查的目标类型 String 就出现了三次。在使用了 instanceof 模式匹配之后,代码可以简化很多。在下面的代码中, String s 表示类型模式,其中 String 是需要匹配的类型,s 是匹配成功之后用来捕获目标对象的变量。该变量 s 可以直接在 if 语句块中使用。

if (obj instanceof String s) {System.out.println(s.toUpperCase());}

模式变量使用的是流作用域(flow scoping)。一个模式变量能够出现在作用域中,当且仅当编译器可以推断出模式匹配必定成功,并且该变量被赋予了一个值时。在上面的例子中,if 语句块的代码只有在模式匹配成功了之后才会执行,变量 s 此时必定被赋予了值 obj,因此编译器可以确定 s 必定在 if 语句块的作用域中。

关于流作用域,其实不用了解太多。如果使用错误,编译器会提示你的。

下面的代码给出了 instanceof 模式匹配的代码示例。第一个 if 匹配 String 类型的同时,加上了对字符串长度的检查;第二个 if 匹配剩下的 String 类型的对象。在第一个 if 的条件中,obj instanceof String s 和 s.length() > 10 的顺序不能反过来。这里利用了 && 的短路(short-circuit)特性,当第一个 instanceof 模式匹配成功之后,才会执行后面的判断,这个时候 s 必然是一个 String 对象,可以安全地使用 length 方法;如果第一个 instanceof 模式不匹配,后面的判断不会被执行,因此也不会出现错误。

public class StringMatch {public void test(Object obj) {if (obj instanceof String s && s.length() > 10) {System.out.println(“长字符串 -> ” + s);} else if (obj instanceof String s) {System.out.println(“短字符串 -> ” + s);} else {System.out.println(“其他”);}}}

在 switch 语句和表达式中使用模式匹配

在 Java 17 中,switch 语句和表达式的 case 子句中可以使用模式匹配。该功能在 Java 17 中是预览功能,因此需要通过命令行参数 –enable-preview 来启用。switch 在很多时候可以替代嵌套的 if/else。

下面的代码使用 switch 语句加上模式匹配改写了上面的使用嵌套 if/else 的代码示例。使用 switch 比 if/else 更加简洁。这里的 switch 用的是箭头格式。

public class StringMatch {public void test(Object obj) {switch (obj) {case String s && s.length() > 10 -> System.out.println(“长字符串 -> ” + s);case String s -> System.out.println(“短字符串 -> ” + s);default -> System.out.println(“其他”);}}}

我们可以用 switch 语句改写文章开头提到的对象格式化的方法,如下面的代码所示。使用 switch 语句加上模式匹配的代码更加简洁易懂。

public class ObjectFormatter {public String format(Object input) {return switch (input) {case null -> “”;case Number n -> NumberFormat.getNumberInstance().format(n);case LocalDateTime t -> t.format(DateTimeFormatter.ISO_DATE_TIME);default -> input.toString();};}}

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年9月4日
下一篇 2022年9月4日

相关推荐

  • 穿衣搭配也能少走弯路!女人牢记这“3要”原则,时髦显气质

    会穿衣的女性,她们往往能游刃有余地驾驭各类单品,塑造出符合自身体型的着装。不管年纪多大,都要牢记“三要”原则,穿衣搭配少走弯路,大气又显气质。 服装搭配要利落 夏日的穿搭过程会更加…

    2022年5月18日
  • 荣耀悄然上架,新机仅售1099!长得像iPhone13

    荣耀悄然发布千元新机:荣耀Play 30,1099元起。据悉,该机背面的摄像头采用了对角线设计,看起来很像“十三香”iPhone13。 不过也有网友表示:荣耀玩30比iPhone1…

    2022年8月26日
  • 做品牌不是更难了,而是更简单了

    消费者洞察分为三部分:一是主流消费群体的结构洞察,二是主流消费群体的集体行为特征洞察,三是消费者生活方式洞察。众所周知,“95后”和“00后”即将成为社会消费的主力军,这是主流消费…

    2022年8月5日
  • 腾讯ROG游戏手机6Pro评测:或许是第一款榨干骁龙8+的产品

    对于游戏玩家来说,ROG这个名字一定不会陌生。作为目前国内的顶级高端硬件设备品牌之一,ROG的产品在配置、设计以及做工方面都可圈可点,赢得了不少消费者的喜爱。 腾讯ROG游戏手机6…

    2022年7月7日
  • 深入了解什么是JS中的闭包

    什么是闭包?相信很多人听了有点懵,然后去百度查了一下官方的定义“闭包就是能够读取其他函数内部变量的函数”发现感觉自己更懵了。关于闭包如果只看那官方的定义的话确实不是让人很容易理解。…

    2022年6月30日
  • 余承东最新发声:汽车是华为唯一亏损的业务!建议尽快淘汰纯燃油车;问界M7订单已破6万台

    近日刚发布的AITO问界M7香了,据官方战报,72小时内订单已超过6万台,而上一代产品M5在6月份订单破万。 不过,7月7日,华为消费者业务BG余承东在中国汽车蓝皮书论坛上最新透露…

    2022年7月9日
  • 洗地机中的“机皇”,追觅M13首测

    【第一步, 先关注我】 大家好, 我是胡侃侃。 前言 清洁类家电在最近一年, 各个品牌都在加大产品力上面的投入, 我深度使用了多个品牌的二十多款扫拖机器人, 十多款的洗地机产品, …

    2022年8月8日
  • 微信键盘怎么换皮肤变成黑色 深色模式设置关闭教程

    微信键盘0.9.3新版本即将上线,那么在新版本中都更新了什么内容呢?感兴趣的玩家们一起来看看微信键盘0.9.3更新介绍吧,不要错过了。 微信键盘0.9.3更新介绍 微信键盘0.9.…

    2022年10月9日
  • 入驻京东慧采的资质

    慧采平台,是京东大客户为企业级客户打造的研发零投入的专属采购平台。对于没有自建采购管理系统的企业,则可直接使用京东的慧采平台,迅速打造出企业专属的采购平台 慧采又分为了三种模式 第…

    2022年7月2日
  • Python程序开发之简单小程序实例(3)-打印99乘法口诀表

    Python程序开发之简单小程序实例 (3)-打印99乘法口诀表 一、项目功能 在屏幕中打印格式化的九九乘法口诀表。 二、项目分析 按九九乘法口诀的运算顺序,打印的口诀表共有9行9…

    2022年6月22日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息