Java 17 的 switch 模式匹配中,通配符 _ 仅作“忽略绑定”占位符,不参与解构或类型检查;仅允许在 sealed 类或枚举等穷尽类型中作为兜底分支,且不可与其他模式混用。

Java 17 的 switch 表达式支持模式匹配(JEP 406),但通配符(_)在该上下文中不是解构模式,也不参与类型检查。它仅作为“忽略绑定”的占位符,且有明确的语法限制和语义规则。
通配符 _ 不是解构模式
在 Java 模式匹配中,解构模式(如记录模式 Point(int x, int y)、类型模式 String s)会绑定变量并执行结构或类型检查。而通配符 _ 不引入任何变量,也不触发对象解构或字段访问:
- 它不读取目标值的任何字段,不调用
deconstruct方法(对记录而言) - 它不检查目标是否为某个具体类型(不像
String s会做instanceof String) - 它的作用纯粹是“接收任意值,且不关心它是什么”——类似传统
default分支的简化写法,但更精确地用于“已知类型范围内的兜底”
通配符只允许出现在已穷尽的类型模式之后
Java 要求使用通配符时,必须确保所有可能的类型分支已被显式覆盖(即 switch 是“穷尽的”)。编译器依据 sealed 类型层级或枚举来验证这一点:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 若
switch的目标类型是sealed类(如Shape),且所有子类(Circle,Rect,Triangle)都已作为 case 出现,则允许case _ -> ... - 若目标是普通非 sealed 类(如
Object),则case _不被允许——编译报错:"_is not allowed in non-exhaustive switch" - 枚举类型同理:只有所有枚举常量都被列为 case 后,才可添加
case _
通配符不进行运行时类型检查
与类型模式(如 case String s:)不同,通配符分支在运行时不会插入 instanceof 检查:
- 它直接跳转执行,前提是编译期已确认该分支在逻辑上“不可达”或“仅用于兜底”
- 这意味着:即使传入一个未声明的子类实例(在违反 sealed 约束的前提下),JVM 也不会因通配符而抛异常;但该代码根本无法通过编译
- 它不提供类型安全保证,只是语法糖——真正的类型安全由 sealed 层级和编译器穷尽性检查保障
不能与其它模式混用,也不能用于解构上下文
通配符是独立的、原子的模式,不允许组合或嵌套:
-
错误:
case Point(_, _) -> ...(记录模式中不支持通配符字段) -
错误:
case String _ -> ...(不能将_当作变量名用于类型模式) -
错误:
case _ instanceof String -> ...(通配符不能参与表达式) -
正确:
case Circle c -> ...; case Rect r -> ...; case _ -> throw new IllegalStateException("unreachable");
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










