这篇文章我们借助新版Java来理解模式匹配,Rust版的模式匹配稍后就端上来,各位先尝尝Java这杯老咖啡还香不香😄。
什么是模式匹配?
下图直观的表达了模式匹配的概念。

所谓模式 类似上图中木盒的各种形状的洞洞,我们的值只有匹配木盒上面的洞洞才能放进去。 我们看到上面的和木盒有很多不同的形状,意味着模式是多种多样的。
模式匹配是一种通用的技术,可以用于匹配各种类型的数据,包括字符串、树、列表等。例如,正则表达式就是一种特殊类型的模式匹配,专门用于匹配字符串。
正则表达式 使用一系列特殊字符来定义模式。例如,正则表达式 \d+ 可以匹配任何由一个或多个数字组成的字符串。
我们把模式和匹配分开来看。
            
            
              java
              
              
            
          
          Pattern pattern = Pattern.compile("\\d+");
String text = "12345abc67890";
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
	System.out.println("The matched substring is: " + matcher.group());
}
// 程序输出:
The matched substring is: 12345
The matched substring is: 67890
        这段代码中模式 就是Pattern对象,匹配 就是Matcher对象。程序运行过程就是,先创建一个模板有一个或多个数字,然后在text字符串中匹配出符合模板的字符串,最后print到标准输出。
理解了模式匹配这个概念以后,我们就来看新版Java中的模式匹配语法。到这里还不懂模式匹配请趴网线敲我。
Java中的模式匹配
Java 中的模式匹配是一种新的语言特性,于 Java 14 中引入。它允许您使用更简洁的语法来检查对象的类型和提取其值。
模式匹配由两个部分组成:
- 模式:描述要匹配的对象,描述了数据的形状。
 - 绑定变量:用于存储从匹配对象中提取的值。
 
以下是一个简单的示例:
            
            
              java
              
              
            
          
          Object obj = "Hello, world!";
if (obj instanceof String str) {
  System.out.println(str.toUpperCase());
}
        在这个例子中,模式是 String str。它描述了一个类型为 String 的对象。绑定变量是 str,它用于存储从匹配对象中提取的值。
如果 obj 变量引用一个 String 对象,则模式匹配将成功。那么,我们说obj的值是匹配String模式的。然后,str 变量将包含该对象的字符串值。
模式匹配可以用于各种场景,包括:
- 检查对象的类型
 - 从对象中提取值
 - 将对象转换为不同的类型
 
以下是一些更高级的模式匹配示例:
- 类型模式:用于匹配特定类型的对象。
 
            
            
              java
              
              
            
          
          Object obj = 123;
if (obj instanceof Integer i) {
  System.out.println(i * 2);
}
        - 记录模式:用于匹配具有特定属性的记录。
 
            
            
              java
              
              
            
          
          record Person(String name, int age) {}
Person person = new Person("John Doe", 30);
if (person instanceof Person(String name, 30)) {
  System.out.println("Hello, " + name + "!");
}
        - 数组模式:用于匹配数组。
 
            
            
              java
              
              
            
          
          int[] numbers = {1, 2, 3};
if (numbers instanceof int[] arr && arr.length == 3) {
  System.out.println("The array contains three elements.");
}
        从 Java 17 开始,switch 语句也支持了模式匹配。
            
            
              java
              
              
            
          
          Object obj = ...;
String name;
switch (obj) {
  case Person person:
    name = person.getName();
    break;
  case Company company:
    name = company.getName();
    break;
  default:
    throw new IllegalArgumentException("The object is not a Person or Company");
}
        在Java 17之前,我们实现同样的功能需要这样写:
            
            
              java
              
              
            
          
          Object obj = ...;
String name;
if (obj instanceof Person) {
  name = ((Person) obj).getName();
} else if (obj instanceof Company) {
  name = ((Company) obj).getName();
} else {
  throw new IllegalArgumentException("The object is not a Person or Company");
}
        这段代码看起来不怎么优雅,不过它实现了同样的功能。
总结
从广义上说,模式匹配是一种"设计模式",不止编程语言,各种领域都有这种思想。从编程语言这个领域来看,它是先定义好模板,然后看数据是否符合这个模板,主要用于需要判断的场景。同时模式匹配不是必须的,它是一种高级的语法糖,即便没有模式匹配,功能也一样能实现。它的好处是提供了一种更加简洁的表达方式。
Java这个老古董都支持模式匹配,在Rust中肯定也支持了,下篇文章我们介绍Rust语言的模式匹配。