这篇文章我们借助新版Java来理解模式匹配,Rust版的模式匹配稍后就端上来,各位先尝尝Java这杯老咖啡还香不香😄。
什么是模式匹配?
下图直观的表达了模式匹配的概念。
所谓模式类似上图中木盒的各种形状的洞洞,我们的值只有匹配木盒上面的洞洞才能放进去。
我们看到上面的和木盒有很多不同的形状,意味着模式是多种多样的。
模式匹配是一种通用的技术,可以用于匹配各种类型的数据,包括字符串、树、列表等。例如,正则表达式就是一种特殊类型的模式匹配,专门用于匹配字符串。
正则表达式使用一系列特殊字符来定义模式。例如,正则表达式 \d+
可以匹配任何由一个或多个数字组成的字符串。
我们把模式和匹配分开来看。
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 中引入。它允许您使用更简洁的语法来检查对象的类型和提取其值。
模式匹配由两个部分组成:
- 模式:描述要匹配的对象,描述了数据的形状。
- 绑定变量:用于存储从匹配对象中提取的值。
以下是一个简单的示例:
Object obj = "Hello, world!";if (obj instanceof String str) {System.out.println(str.toUpperCase());
}
在这个例子中,模式是 String str
。它描述了一个类型为 String
的对象。绑定变量是 str
,它用于存储从匹配对象中提取的值。
如果 obj
变量引用一个 String
对象,则模式匹配将成功。那么,我们说obj的值是匹配String模式的。然后,str
变量将包含该对象的字符串值。
模式匹配可以用于各种场景,包括:
- 检查对象的类型
- 从对象中提取值
- 将对象转换为不同的类型
以下是一些更高级的模式匹配示例:
- 类型模式:用于匹配特定类型的对象。
Object obj = 123;if (obj instanceof Integer i) {System.out.println(i * 2);
}
- 记录模式:用于匹配具有特定属性的记录。
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 + "!");
}
- 数组模式:用于匹配数组。
int[] numbers = {1, 2, 3};if (numbers instanceof int[] arr && arr.length == 3) {System.out.println("The array contains three elements.");
}
从 Java 17 开始,switch 语句也支持了模式匹配。
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之前,我们实现同样的功能需要这样写:
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语言的模式匹配。