4

Java 17 更新(7):模式匹配要支持 switch 啦

 2 years ago
source link: https://www.bennyhuo.com/2021/10/02/Java17-Updates-07-switch/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Java 17 更新(7):模式匹配要支持 switch 啦

发表于 2021-10-02 | 阅读次数: 3
本文字数: 3.9k | 阅读时长 ≈ 7 分钟

说实话,我们总是用人家 JDK 的内部 API,是不是有点儿欺负人。

这一次我们来聊聊 **JEP 406: Pattern Matching for switch (Preview)**。这是一个预览特性。

前面我们提到过 Java 16 引入了一个对于 instanceof 的模式匹配:

// Old code
if (o instanceof String) {
String s = (String)o;
... use s ...
}

// New code
if (o instanceof String s) {
... use s ...
}

这个其实从效果上类似于 Kotlin 的智能类型转换:

if (o is String) {
// now `o` is smart casted to String
println(o.length())
}

0B330ECC.gif

不过,模式匹配可以做的事情更多。

Java 17 引入了一个 preview 的特性,可以通过 switch 语句来实现类似的类型模式匹配:

static String formatterPatternSwitch(Object o) {
return switch (o) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> o.toString();
};
}

对于每一个 case 语句,我们都可以使用类型模式匹配,如果 o 的类型是 Integer,那么它就可以匹配到第一个 case 分支,并且在这个分支内部可以用新变量 i 来替代 o。

请注意,switch 语句在 Java 14 正式支持了表达式,有些朋友可能对这个语法不是很熟悉, 每一个 case 语句后面的 -> 都是一个表达式,并且不会落到下一个 case 分支,所以大家也不会在这里看到 break。不仅如此,switch 表达式的参数 o 的类型也做了放宽,我们在后面介绍密封类的时候还可以看到对这一点的运用。

74379640.jpg

不仅如此,这次 switch 表达式还添加了对 null 的支持:

static void testFooBar(String s) {
switch (s) {
case null -> System.out.println("Oops");
case "Foo", "Bar" -> System.out.println("Great");
default -> System.out.println("Ok");
}
}

这样我们就可以把 null 放到第一个分支来实现空检查了,非常方便。

模式匹配在 Java 的近亲 Scala 上得到了广泛的运用,当然 Scala 的模式匹配要复杂得多,下面是我从 Scala 官网摘的例子:

abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification

def showNotification(notification: Notification): String = {
notification match {
case Email(sender, title, _) => s"You got an email from $sender with title: $title"
case SMS(number, message) => s"You got an SMS from $number! Message: $message"
case VoiceRecording(name, link) => s"You received a Voice Recording from $name! Click the link to hear it: $link"
}
}

case class 类似于 Java 当中的 record,或者 Kotlin 当中的 data class,我们看到下面的 match 语句当中,case Email(sender, tit le, _) 语句可以直接对待匹配的对象做解构。此外,还可以添加模式守卫(Pattern Guard),例如:

def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
notification match {
case Email(sender, _, _) if importantPeopleInfo.contains(sender) => "You got an email from special someone!"
case SMS(number, _) if importantPeopleInfo.contains(number) => "You got an SMS from special someone!"
case other => showNotification(other) // nothing special, delegate to our original showNotification function
}
}

注意每一条 case 后面的 if,在匹配的时候,也需要命中 if 后面的表达式。

74376397.png

Java 在后续的发展过程当中也许也存在添加这样的语法的可能性。

Kotlin 在演进的过程中曾经也一度想要把 when 表达式做成模式匹配,不过可能是后面觉得模式匹配的实用价值不高(???),就没有继续做下去。

7436CC1A.gif

稍微提一下,如果想要体验预览特性,需要为 Java 编译器和 Java 运行时添加 --enable-preview 参数。

好,关于预览的 switch 模式匹配我们就先介绍这么多。


C 语言是所有程序员应当认真掌握的基础语言,不管你是 Java 还是 Python 开发者,欢迎大家关注我的新课 《C 语言系统精讲》:

扫描二维码或者点击链接《C 语言系统精讲》即可进入课程

program_in_c.png


Kotlin 协程对大多数初学者来讲都是一个噩梦,即便是有经验的开发者,对于协程的理解也仍然是懵懵懂懂。如果大家有同样的问题,不妨阅读一下我的新书《深入理解 Kotlin 协程》,彻底搞懂 Kotlin 协程最难的知识点:

扫描二维码或者点击链接《深入理解 Kotlin 协程》购买本书

understanding_kotlin_coroutines.png


如果大家想要快速上手 Kotlin 或者想要全面深入地学习 Kotlin 的相关知识,可以关注我基于 Kotlin 1.3.50 全新制作的入门课程:

扫描二维码或者点击链接《Kotlin 入门到精通》即可进入课程

exported_qrcode_image_256.png


Android 工程师也可以关注下《破解Android高级面试》,这门课涉及内容均非浅尝辄止,除知识点讲解外更注重培养高级工程师意识:

扫描二维码或者点击链接《破解Android高级面试》即可进入课程

15520936284634.jpg


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK