Java 14 引入模式匹配预览版,16 正式支持 instanceof,21 扩展至 switch;可一步完成类型判断与变量绑定,提升类型安全与代码简洁性,并结合 sealed class 实现编译期穷尽性检查。

Java 14 引入了预览版的 模式匹配(Pattern Matching),并在 Java 16 正式成为语言特性(用于 instanceof),Java 21 进一步扩展到 switch 表达式。它能显著简化多态中常见的“先判断类型、再向下转型、再使用”的冗余代码。
用 instanceof 模式匹配替代传统类型检查 + 强制转型
传统写法需要两步:先用 instanceof 判断,再显式强转:
if (obj instanceof Dog) {
Dog dog = (Dog) obj; // 多写一次转型
dog.bark();
}用模式匹配后,一步完成判断和绑定:
if (obj instanceof Dog dog) { // dog 是已转型并声明的局部变量
dog.bark(); // 可直接使用,类型安全、作用域清晰
}关键点:
立即学习“Java免费学习笔记(深入)”;
- 语法是
instanceof Type variableName,编译器自动推导类型并绑定变量 - 变量
dog仅在if块内有效,避免误用或空指针风险 - 无需手动强转,也无需担心
ClassCastException - 支持嵌套模式(如
instanceof Dog d && d.age > 2),但需注意可读性
在 switch 中用类型模式统一处理多种子类
当需根据对象实际类型分发逻辑(比如解析不同消息类型),传统方式常配合 if-else if 链和多次转型:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
if (msg instanceof TextMessage) {
TextMessage t = (TextMessage) msg;
processText(t.content);
} else if (msg instanceof ImageMessage) {
ImageMessage i = (ImageMessage) msg;
processImage(i.url);
} else if (msg instanceof VoiceMessage) {
VoiceMessage v = (VoiceMessage) msg;
processVoice(v.duration);
}Java 21+ 支持 switch 的类型模式,更简洁、更安全:
switch (msg) {
case TextMessage t -> processText(t.content);
case ImageMessage i -> processImage(i.url);
case VoiceMessage v -> processVoice(v.duration);
case null -> throw new IllegalArgumentException("msg is null");
default -> throw new IllegalArgumentException("Unknown message type: " + msg);
}说明:
- 每个
case后直接跟类型和绑定变量,自动完成类型检查与转型 -
null可显式作为 case 处理,避免 NPE -
default覆盖未匹配类型,编译器会提示是否遗漏(若所有已知子类都已覆盖且 sealed,则可能警告 unreachable) - 要求
msg的静态类型是这些类型的公共父类/接口(如Message)
配合密封类(sealed classes)实现穷尽性检查
若父类是 sealed,且所有子类都明确列出(permits),则 switch 类型模式可获得编译期穷尽性保证:
public sealed interface Shape permits Circle, Rectangle, Triangle { }
<p>public record Circle(double radius) implements Shape { }
public record Rectangle(double width, double height) implements Shape { }
public record Triangle(double a, double b, double c) implements Shape { }此时下面的 switch 会被编译器检查:如果漏掉任一 permits 类型,就会报错:
double area = switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> /* Heron's formula */ ... ;
}; // 编译器确保所有子类都被覆盖这比运行时靠 instanceof + else 更可靠,真正实现“类型安全的多态分发”。
注意事项与限制
模式匹配虽好,但需注意适用边界:
- 仅适用于
instanceof和switch,不能用于泛型类型擦除后的运行时判断(如List<String>无法用instanceof List<String>) - 绑定变量名不能与已有变量同名(否则编译错误),且作用域严格受限于对应分支
- 不支持对数组类型做模式匹配(如
instanceof int[] arr合法,但instanceof String[] s在某些旧版本可能受限,建议测试) - 若需多次使用转型后对象,仍建议提取为局部变量——模式绑定变量生命周期短,重复写
case Foo f -> f.xxx()多次没问题,但复杂逻辑建议提前解构

















