判断Map键存在后调用get仍报拆箱空指针警告 实际是否有风险
结论
你当前单线程运行的代码不存在空指针异常风险,该警告属于IDE静态检查的误报,但如果存在多线程并发修改idCollisonMap的场景则会有真实的空指针风险。
警告产生的原因
IDE的静态分析工具无法逻辑上保证containsKey(currentId)和idCollisonMap.get(currentId)两次调用之间,Map的内容不会发生变化,只能识别到get()返回的是包装类型Integer,拆箱为基础类型int做运算时可能为null,因此抛出了这个通用警告。
在你当前的单线程遍历场景下,containsKey判断返回true后没有任何代码会删除对应key的映射,所以get()一定会返回非空的Integer对象,拆箱过程不会触发空指针。
真实存在空指针的场景
如果有其他线程同时操作idCollisonMap,刚好在containsKey返回true之后、get()执行之前删除了currentId对应的映射,此时get()会返回null,拆箱时就会抛出NullPointerException,这种场景下警告就不是误报。
优化建议
可以采用更简洁且无警告的写法实现同样的计数逻辑,不需要写containsKey分支判断:
- 使用
getOrDefault简化逻辑
if (currentId != null) { idCollisonMap.put(currentId, idCollisonMap.getOrDefault(currentId, 0) + 1); }
- 用
merge方法一行实现计数(Java 8及以上版本支持)
if (currentId != null) { idCollisonMap.merge(currentId, 1, Integer::sum); }
如果确认当前场景永远是单线程操作Map,也可以在对应代码行添加@SuppressWarnings("ConstantConditions")注解直接忽略警告。
内容的提问来源于stack exchange,提问作者Kenny Sexton
相关产品推荐
相关产品推荐

