Java switch pattern matching 的 null 分支处理
来源:17golang原创
时间:2026-11-01 06:23:50 364浏览 收藏
Java 21 的 switch pattern matching 可以直接按类型分支,但 null 仍然是一个单独的匹配边界:case Object value 不会自动接住空引用。selector 为 null 且没有 case null 时,switch 会抛出 NullPointerException;要处理它,必须显式写出 case null,或者在确实共享兜底策略时使用 case null, default。
官方文档:https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html
判断口诀:类型模式只负责非 null 对象;null 要单独声明。独立业务写case null,与未知值共用策略才写case null, default,并把合并标签放在最后。
本文要点
- 类型模式不会匹配 null,缺少 null 标签时会抛 NPE。
case null可以与类型模式分开表达空值策略。case null, default只能与 default 合并,且应位于 switch 末尾。
先看清 null 为什么不会命中类型模式
最容易误判的写法是把 Object 当成“所有输入”,然后省略 null 分支。pattern switch 的运行规则会先区分 null 引用;只有非 null 值才继续尝试类型模式。因此下面的 case Object value 能覆盖普通对象,却不能替代 case null。
static String describe(Object value) {
return switch (value) {
// 类型模式只接收非 null 的 Object
case Object object -> "对象:" + object.getClass().getSimpleName();
// 没有 case null 时,value 为 null 会在匹配前抛出 NPE
};
}
这不是 default 是否穷举的问题,而是 null 在模式匹配前就有专门的处理规则。只要 selector 可能为空,就应在设计阶段明确空值是业务状态、缺省值,还是应该直接暴露为异常。

需要独立策略时显式写 case null
如果空值代表“未提供”“尚未加载”或“需要单独提示”,就把它写成独立标签。这样既能保留类型模式的变量,也不会把 null 伪装成一个普通对象。
static String normalize(Object value) {
return switch (value) {
// 空引用是独立业务状态,不访问任何模式变量
case null -> "未提供";
// 只有匹配 String 后,text 才在当前分支内可用
case String text -> "文本:" + text.trim();
// 其他非 null 类型走默认处理
default -> "其他类型:" + value.getClass().getSimpleName();
};
}
这里的顺序也表达了阅读意图:先处理空引用,再处理有明确业务含义的类型,最后由 default 接住剩余非 null 值。case null 不能和 case String text 放在同一个标签里,因为类型模式需要一个可用的非 null 模式变量。
什么时候用 case null, default
当 null 和其他未识别对象确实共享同一套兜底行为时,可以把两个标签合并。它适合“只要不是受支持的 String 就返回通用提示”这类场景,但要注意合并后无法区分到底是 null 还是其他类型。
static String category(Object value) {
return switch (value) {
// 先保留明确的类型分支
case String text -> "文本:" + text;
// null 与未知非 null 对象共享兜底结果
case null, default -> "未分类";
};
}
case null, default 是合法的合并标签,但它不能再与后续标签混用,应放在最后。若后续还想区分数字、日期等类型,应改回独立的 case null 加具体类型模式,再用单独的 default 收尾。

编译前按四个边界检查
| 检查项 | 正确判断 | 常见误区 |
|---|---|---|
| 类型模式 | 只匹配非 null 对象 | 把 Object 模式当成 null 兜底 |
| 空值策略 | 独立写 case null | 试图写 case null, String s |
| 合并兜底 | case null, default 放在末尾 | 后面继续添加 case |
| 模式变量 | 只在匹配成功的分支使用 | 在 null/default 分支引用 String 变量 |
如果 switch 需要返回结果,增强型 switch 表达式或带模式的 switch 语句还必须满足穷举要求。最小可行的工程决策是先列出 null、已知类型和未知类型三类输入,再决定是分别记录、统一兜底,还是让异常尽早暴露。
常见问题
有了 default,为什么 null 仍然抛 NPE?
default 只处理非 null 值中没有命中其他标签的情况。null 要由 case null 或 case null, default 明确覆盖。
case null, default 能放在中间吗?
不能把它当作普通中间分支继续往下写;该合并标签相当于最终兜底,应位于 switch 的末尾。
-
501 收藏
-
文章 · java教程 | 1个月前 | Java · 异常处理 · 资源管理 · java try-with-resources AutoCloseable close suppressed exception501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
112 收藏
-
254 收藏
-
158 收藏
-
159 收藏
-
239 收藏
-
463 收藏
-
490 收藏
-
390 收藏
-
269 收藏
-
340 收藏
-
446 收藏
-
266 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习