184. Java 模式匹配 - instanceof 模式匹配详解
从 Java 16 开始,instanceof 引入了“模式匹配(Pattern Matching)”的能力,使得代码更简洁、可读性更高。
🧠 什么是 instanceof 模式匹配?
我们以前使用 instanceof 判断类型时,往往还要显式地进行类型转换(cast)。而从 Java 16 开始,我们可以在 instanceof 判断的同时,声明一个变量用于接收匹配后的结果。
✅ 基本用法示例
public void print(Object o) {
if (o instanceof String s) {
System.out.println("This is a String of length " + s.length());
} else {
System.out.println("This is not a String");
}
}
🧩 背后的三个组成部分
| 要素 | 含义 | 示例 |
|---|---|---|
匹配目标(Target) | 要进行判断的对象 | o |
模式(Pattern) | 判断的类型 + 变量名 | String s |
匹配结果(Result) | 模式变量(Pattern Variable) | s,类型为 String,只在匹配成功时创建 |
🔄 模式变量的范围
模式变量(如 s)的作用域限定在判断成功的逻辑分支内。你可以在 if 的代码块中使用,也可以在布尔表达式中进行进一步判断。
🎯 示例:匹配字符串且不为空
public void print(Object o) {
if (o instanceof String s && !s.isEmpty()) {
System.out.println("Non-empty String of length " + s.length());
} else {
System.out.println("Not a non-empty String.");
}
}
💡 只有在
o instanceof String s为真时,才会创建变量s,因此!s.isEmpty()是安全的。
🧹 Java 16 前的写法 vs Java 16 后的改进
🧾 Java 16 前:
public void print(Object o) {
if (!(o instanceof String)) {
return;
}
String s = (String) o;
System.out.println("This is a String of length " + s.length());
}
🚀 Java 16 模式匹配写法:
public void print(Object o) {
if (!(o instanceof String s)) {
return;
}
System.out.println("This is a String of length " + s.length());
}
✅ 更简洁、类型转换由编译器自动完成,代码更安全、清晰。
💥 编译器智能分析
有些判断永远不会成立,编译器能直接报错:
Double pi = Math.PI;
if (pi instanceof String s) {
// ❌ 编译错误:Double 永远不可能是 String 的实例
}
因为 String 是 final 类,不能被继承,因此不可能出现 Double 是 String 的情况。
🏗️ 更优雅的 equals() 写法示例
下面是经典的 equals 方法(传统写法):
public class Point {
private int x;
private int y;
public boolean equals(Object o) {
if (!(o instanceof Point)) {
return false;
}
Point point = (Point) o;
return x == point.x && y == point.y;
}
}
✨ 使用模式匹配后的重写版本:
@Override
public boolean equals(Object o) {
return o instanceof Point point &&
x == point.x &&
y == point.y;
}
👌 优点:去掉了冗余的类型转换(cast),代码更短更清晰!
📌 小结
| 特性 | 说明 |
|---|---|
| ✅ 自动类型转换 | 匹配成功后,自动为你声明并转换变量 |
| ✅ 安全简洁 | 减少强制类型转换,避免 ClassCastException |
| ✅ 条件控制更灵活 | 可与 && |
| ✅ 可读性提升 | 大幅减少冗余代码,逻辑清晰 |
🧠 附加:类型兼容性说明
你可以使用 instanceof 模式匹配 类、抽象类、接口,例如:
if (o instanceof CharSequence cs) {
System.out.println("Length: " + cs.length());
}
因为 String 实现了 CharSequence,因此匹配成功。