作者:l拉不拉米\
链接:https://juejin.cn/post/703144...

一、前言

Hello 大家好,我是l拉不拉米,明天带来一个实在案例,让大家更粗浅的了解空指针异样

公司刚入职了一名中级Java开发,通过一个星期的适应学习,各方面体现还不错,于是调配了一个小的迭代给新人做。

需要很简略,把从第三方拉取的数据匹配到本身公司后盾设置的渠道后,聚合到一个列表中,批量入库。

然而就在匹配的逻辑中,上线后报了个NPE,这是作为一名中级开发不应犯的简略谬误,新人被我狠狠的训了,记生产事变一次。

二、事变重现

伪代码

阐明:伪代码并非实在线上代码,只是为了更不便,更形象的重现事故现场而编写的;实在的业务场景往往更加简单,NPE的破绽暗藏在更深处,不易code view进去,也不易测试进去;生产环境NPE是较常见的异样,心愿大家不要纠结为什么测试没测进去,要害还是通过这样一个案例理解NPE的起因和解决方案。
// 后盾设置的渠道String channelNo = channelDao.getOne().getChannelNo();// 第三方拉取的数据List<ThirdData> thirdDataList = httpClientUtils.getThirdDatas(DateUtils.today());// 匹配过滤thirdDataList.stream().filter(o ->channelNo.equals(o.getChannelNo())).collect(Collectors.toList());// 批量入库thirdDataDao.saveAll(thirdDataList);

举荐一个开源收费的 Spring Boot 最全教程:

https://github.com/javastacks/spring-boot-best-practice

剖析与解决

有教训、技术扎实的同学看到这里应该或多或少能发现问题了。其实啊,这四段代码是作者精心设计的,堪称是卧龙凤雏

短短四行代码竟然凑齐了3个NPE,我枯了/(ㄒoㄒ)/~~

咱们逐行剖析:

第一行剖析

channelDao.getOne()如果返回为null,那么调用getChannelNo()会报NPE

解决办法

1、应用防御性编程,提前返回(需依据具体业务场景而定)

// 如果channelNo是办法逻辑执行的必须元素,举荐用此办法Channel channel = channelDao.getOne();if (channel == null) {    return;}

2、应用三目运算,返回空字符串("")

// 返回兜底的空字符串String channelNo = channelDao.getOne() == null ? "" : channelDao.getOne().getChannelNo();

3、应用Optional函数,返回空字符串("")

String channelNo = Optional.ofNullable(channelDao.getOne()).orElse("");

第三行剖析(1)

thirdDataList如果为null,那么调用stream()会报NPE

通过上面的源码截图就能晓得起因:

解决办法

1、应用防御性编程,提前返回(举荐)

// 举荐应用汇合工具类判空if (CollectionUtils.isEmpty(thirdDataList)) {    return;}

2、应用if条件语句包裹(不举荐)

if (CollectionUtils.isNotEmpty(thirdDataList)) {    // 执行前面的逻辑}

第三行剖析(2)

channelNo如果返回为null,那么执行channelNo.equals(o.getChannelNo())会报NPE

咱们晓得,按Java的标准String的equals()办法的调用,要求右边是确定值,就是为了防止调用方为null的状况。然而这里调用方和equals的入参都是变量,这种状况该怎么办呢?

1、再加一句判断:

channelNo != null && channelNo.equals(o.getChannelNo())

2、其实能够用java.uti包下的Objects类的equals办法

Objects.equals(channelNo, o.getChannelNo())

看源码高深莫测,该办法对右边的对象做了非空判断

3、用其余开源的工具类库或者本人实现

如:

org.apache.commons.lang3.StringUtilscn.hutool.core.util.StrUtil;

最初

在这里l拉不拉米要举荐一款IDEA的插件:

SonarLint

能动静的帮您查看代码破绽,像NPE这种代码危险都会给于相应的提醒。

SonarLint还有一个赫赫有名的服务端叫SonarQube

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!