Map.of传了个null本地没事一部署就炸了

发布时间:2026/7/18 4:51:58
Map.of传了个null本地没事一部署就炸了 CommonAuthFilter 里写了一段返回 401 的代码privatevoidwriteUnauthorized(HttpServletResponseresponse,Stringmsg){response.setContentType(application/json);response.setStatus(401);objectMapper.writeValue(response.getWriter(),Map.of(code,401,message,msg,data,null));}本地跑得好好的。打成 JAR 部署上去用户登录失败——白屏。不是 401不是 500是白屏。Nginx 日志 200但响应体是空的。排查本地跑了一下线上的请求没复现。看了半天没头绪最后在writeUnauthorized里加 try-catchtry{objectMapper.writeValue(response.getWriter(),Map.of(code,401,message,msg,data,null));}catch(Exceptione){e.printStackTrace();// → NullPointerException}NPE。堆栈指到Map.of()。根因Map.of() 不接受 nullMap.of()是 Java 9 引入的不可变 Map 工厂方法。一行代码创建只读 MapMapString,ObjectmapMap.of(a,1,b,2);// ✅ 正常但它的实现里显式检查了 null// JDK 源码MapN 内部类staticK,VMapK,Vof(Kk1,Vv1,Kk2,Vv2,Kk3,Vv3){if(k1null||v1null||k2null||v2null||k3null||v3null){thrownewNullPointerException();}returnnewMapN(newObject[]{k1,v1,k2,v2,k3,v3});}任何一个 key 或 value 为 null直接 NPE。没有「部分允许」——要么全非 null要么别用。上面那行Map.of(code, 401, message, msg, data, null)因为null炸了。为什么本地没事部署就炸本地开发时profiles.activedevdev 环境 token 正常不会走到writeUnauthorized分支。部署到线上用户 token 过期或非法才触发这个分支——本地根本没执行过这段代码。这就是「环境差异导致的隐藏 bug」——代码在特定路径下才有问题本地测试覆盖不到上生产第一次调用就炸。正确写法如果需要 null value// ✅ HashMap 允许 null key 和 null valueMapString,ObjectbodynewHashMap();body.put(code,401);body.put(message,msg);body.put(data,null);如果不需要 null value// ✅ 不传 data 字段前端收到 JSON 后做空值判断Map.of(code,401,message,msg);其他不可变集合也有同样限制方法限制Map.of()key 和 value 都不能为 nullMap.ofEntries()key 和 value 都不能为 nullList.of()元素不能为 nullSet.of()元素不能为 nullMap.copyOf()源 Map 不能含 null key/valueMap.of()的 NPE 容易让人懵——因为调用栈里不会出现你的业务代码直接抛在 JDK 底层。一眼看不出是自己传了 null。Map.of()是简洁但 null 零容忍。如果你不确定某个值是不是 null用new HashMap()保平安。关于作者无羡独立开发者全栈工程师专注 AI 应用与微服务架构。 分类技术复盘 个人博客 — 更多技术文章✨ 开发者福利整理 — 云服务资源汇总 软件工坊 — 我的技术分享 个人门户 — 独立开发作品全集