3个程序员都没解决掉的一个包装类型和非包装类型的NULL异常

JAVA herman 135浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xmtxtt,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序

让开,我要开始装逼了。因为 3 个程序员都没解决掉的一个 null 异常,被我这个第四个程序员解决了。就问你们服不服,我能解决空异常。。。

事情的起因是这样的,电商系统新版本增加了一个小功能。在发货模块有一个小需求要改动,程序员 A 更改了其中的一个方法。然后放在测试环境进行测试。这个方法时而报 NULL 异常,时而又正常。

他排查了半天,没搞定。然后依托程序员 B 前来解决,程序员 B 看了半天,没发现问题。又依托程序员 C 来解决,同样的失败了。发生车祸的代码简化如下:

try{
    long status = 0L;
    Long xttblog = null;
    System.out.println(xttblog == status);
}catch (Exception e){
    e.printStackTrace();
}

解释一下,就是有一个为 0 的状态变量 status 与一个数据库中查询出来的状态进行比较。实际代码中加上了层层的判断,!= null 的判断非常多。但是他们没想到包装类型 Long 和非包装类型 long 会出现空异常。另外一个产生这个问题的原因是,他们认为从数据库查询出来的那个 Long 不可能为空。但实际上程序员在测试过程中偷了懒,为了不删掉数据,他把需要删除的数据的主键 id 改为小于 0 的负数,最终导致了一些数据查询不出来。而调试的时候,全是正常,一到测试环境,测试一测就翻车。

上面这个代码为什么会发生空异常呢?是因为当一个包装类型和非包装类型进行 == 比较时,会进行拆箱操作。最终会转化成非包装类型进行比较,而值为 null 的包装类型 Long 在转换过程中无法正常转换就回跑出 NULL 异常。

车祸代码

这一点,我们也可以从 Long 重写的 equals 方法上看出问题。

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

而实际上,在《阿里巴巴Java 开发手册》中,已经有了明确的强制性要求了。虽然说和我们这一个有些差异,但也是也可以借鉴的。

《阿里巴巴Java 开发手册》

最后,一定要注意。用==比较包装类型和非包装类型的时候,包装类型对象被拆箱(转为非包装的基本类型)。

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » 3个程序员都没解决掉的一个包装类型和非包装类型的NULL异常