nullpointerexception最危险之处在于隐式空值传播,87%线上npe源于四类陷阱:自动拆箱崩塌、集合元素为null直取、方法参数未校验、字符串比较顺序错误。

NullPointerException(NPE)最危险的地方,往往不是明晃晃的 String s = null; s.length();,而是那些看似安全、IDE不报错、单元测试也容易漏过的隐式空值传播路径。87% 的线上 NPE 来自这三类“安静”的陷阱。
自动拆箱时的静默崩塌
包装类型参与运算或赋值时,JVM 会自动调用 xxxValue() 方法拆箱。一旦该对象为 null,异常当场抛出,且无任何编译警告。
-
典型代码:
Integer count = null; int result = count + 10;—— 实际执行count.intValue(),直接 NPE -
更隐蔽的情况:方法返回
Optional<integer></integer>,却写成int value = optional.orElse(null);,后续再参与计算 -
稳妥做法:涉及算术、比较、赋值前,显式判空或使用
Objects.requireNonNull(count, "count 不能为空");优先用Optional.ofNullable(count).orElse(0)
集合元素为null却直取直用
集合本身不为 null,不代表里面存的每个元素都非空。尤其在数据库映射(如 MyBatis)、远程调用或用户输入解析后,null 元素极易混入。
-
高频翻车点:
list.get(0).trim()、map.get("id").toString()、array[0].hashCode() -
误区提醒:
CollectionUtils.isNotEmpty(list)只校验集合非空,不校验元素;list.size() > 0同理 -
推荐方式:取值后立刻封装为
Optional.ofNullable(list.get(0)).map(String::trim).orElse("");或预过滤:list.stream().filter(Objects::nonNull).collect(Collectors.toList())
方法参数未做防御性校验
外部传入的参数(REST 请求体、RPC 返回值、回调函数入参)天然不可信。开发者常默认“上游已校验”,结果在链路下游某处突然炸开。
-
典型场景:接口接收
@RequestBody User user,直接调用user.getAddress().getCity();或 RPC 返回Response<data></data>,直接response.getData().size() -
简单有效手段:在方法入口用
Objects.requireNonNull(user, "user 不能为空")快速失败;Spring 中配合@Valid+@NotNull注解实现声明式校验 -
设计层面建议:对外暴露的方法,参数尽量用
Optional<t></t>显式表达可空性;避免返回null,改用Collections.emptyList()或Optional.empty()
字符串与常量比较顺序颠倒
这是初学者易犯、老手也会手滑的低级但高频错误。把变量放前面调用 equals,等于主动给 NPE 开门。
-
危险写法:
if (status.equals("SUCCESS"))—— status 为null时立即崩溃 -
安全写法:
if ("SUCCESS".equals(status))—— 常量非空,equals内部已做 null 判断 -
扩展提醒:同理适用于
equalsIgnoreCase、contains等所有字符串实例方法;对两个变量比较时,必须先判空:status != null && status.equals(other)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











