记忆深刻的一次BUG,久久不能忘怀
三目运算符报NPE了!!!??
第一次遇到的时候,年幼无知的我,觉得明明就是很简单的一行代码,怎么会报错,百思不得其解。
模拟问题代码
public class Test {
private Long money;
public Long getMoney() {
return money;
}
public void setMoney(Long money) {
this.money = money;
}
public static void main(String[] args) {
Test test = new Test();
Long money = Objects.nonNull(test) ? test.getMoney() : 0L;
System.out.println(money);
}
}
输出结果
Exception in thread "main" java.lang.NullPointerException
at com.gree.invoice.b2c.test.Test.main(Test.java:26)
Process finished with exit code 1
## 怎么让代码不报错
两种方法返回结果不一样,根据实际场景选择使用。
方法一:使用Long.valueOf()
,输出结果为null。
// 输出结果 null
Long money = Objects.nonNull(test) ? test.getMoney() : Long.valueOf(0L);
方法二:对money字段进行判空,输出结果为0。
// 输出结果 0
Long money = Objects.nonNull(test) && Objects.nonNull(test.getMoney()) ? test.getMoney() : 0L;
原因解析
参考:《新版阿里巴巴Java开发手册》提到的三目运算符的空指针问题到底是个怎么回事?
Long money = Objects.nonNull(test) ? test.getMoney() : 0L;
因为三目运算符的第二,第三位操作数分别为基本数据类型和包装类对象时,根据表达式返回值类型,包装类对象会自动进行拆/装箱操作。
实际运行的代码为:Long money = Long.valueOf(Objects.nonNull(test) ? test.getMoney() : 0L);
因为0L
为基本数据类型long
,Long money
要求返回值为包装类型,会触发自动装箱操作,而test.getMoney()
为null,Long.valueOf(null)就会导致NPE。
其实,《阿里巴巴Java开发手册(泰山版)》中也有提及:
编码好习惯
那么平时怎么避免这种问题呢?
那就是保持三目运算符的第二位和第三位表达式的类型一致,最后要做好单元测试。
这也就是为什么改成Long money = Objects.nonNull(test) ? test.getMoney() : Long.valueOf(0L);
不会再报错的原因了。
有缘下次再见
转载自:https://juejin.cn/post/7221783654539968572