Java开发中避免空指针异常的真实案例分析与教训总结

大家好,我是Java架构师

Java开发中避免空指针异常的真实案例分析与教训总结

一、前言

大家好,我是 l 拉不拉米。今天给大家带来一个真实案例,以便让大家能更深刻地理解空指针异常。

公司新入职了一位中级 Java 开发人员。经过一周的适应与学习后,其在各方面的表现都较为良好。因此,为这位新人分配了一个较小的迭代任务让其去做。

需求较为简单,需将从第三方拉取的数据与自身公司后台所设置的渠道进行匹配,接着把匹配后的数据聚合到一个列表里,最后将其批量入库。

然而在匹配的逻辑方面,上线之后出现了一个 NPE 。这是一名中级开发不应该犯的较为简单的错误,我狠狠地训斥了那个新人,并且记录了一次生产事故。

二、事故重现伪代码

伪代码并非真实线上代码,只是为方便、形象地重现事故现场而编写;真实业务场景更复杂,NPE 漏洞隐藏较深,不易通过 code view 看出,也不易测试出来;生产环境中 NPE 是较常见的异常,希望大家不要纠结为何测试未测出,关键是通过此案例了解 NPE 的原因和解决方案。

// 后台设置的渠道
获取到的一个对象,通过 channelDao.getOne() 获取到,该对象的 channelNo 属性被赋值给了 String 类型的变量 channelNo 。
// 第三方拉取的数据
ListthirdDataList 等于 httpClientUtils 获取的今日的第三方数据,即 httpClientUtils.getThirdDatas(DateUtils.today());
// 匹配过滤
从 thirdDataList 中筛选出满足条件的元素,条件是元素的 channelNo 与指定的 channelNo 相等,然后将筛选后的元素收集为一个列表。
// 批量入库
thirdDataDao 对 thirdDataList 进行保存操作,即将 thirdDataList 中的所有数据保存起来。

分析与解决

有经验且技术扎实的同学看到此处,应该能发现一些问题。实际上,这四段代码是作者精心构思的,它们可以说是各有特点,就像卧龙和凤雏一样。

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

推荐一个开源免费的 Spring Boot 最全教程:

我们逐行分析:

第一行分析

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

解决办法:其一,运用防御性编程,提前进行返回操作,不过这需依据具体的业务场景来确定。

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

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

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

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

牛逼啊!接私活必备的 N 个开源项目!赶快收藏

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

l,那么调用stream()会报NPE。建议你看下。

通过下面的源码截图就能知道原因:

解决办法1、使用防御性编程,提前返回(推荐)

// 推荐使用集合工具类判空
if如果 thirdDataList 为空(即 CollectionUtils.isEmpty(thirdDataList) 为 true),那么 {
    return;
}

2、使用if条件语句包裹(不推荐)

if若 thirdDataList 不是空的,就会:
    // 执行后面的逻辑
}

第三行分析(2)

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

我们知晓,依据 Java 的规范,对于 String 的 equals()方法的调用,需要左边是确定的值,这样做的目的是避免调用方为 null 的情况。然而在此处,调用方以及 equals 的入参均为变量,面对这种情况应当如何处理呢?另外,倘若搜索公众号顶级算法的后台并回复“算法心得”,便可以获取一份令人惊喜的礼包。

1、再加一句判断:

channelNo != nullchannelNo 与 o.getChannelNo()相等

其实可以使用 java.uti 包中的 Objects 类的 equals 方法。

Objects 对 channelNo 和 o.getChannelNo()进行比较,判断它们是否相等。

看源码一目了然,该方法对左边的对象做了非空判断

3、用其他开源的工具类库或者自己实现

如:

Apache 旗下的 commons-lang3 库中的 StringUtils 类。
cn.hutool.core.util.StrUtil;

最后

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

SonarLint

可以动态地为您检查代码漏洞,对于像 NPE 这样的代码风险,都会给予相应的提示。

SonarLint 拥有一个较为知名的服务端,这个服务端被称作 SonarQube。

欢迎有需求的同学进行尝试。如果本文对您有帮助,那么也请您帮忙点个赞并且点个在看。

在 GitHub猿 还有更多优质项目系统学习资源,欢迎分享给其他同学吧!

最后整理了 400 多套项目,并且将这些项目赠送给了读者。如果想要获取这些项目,只需扫描下方二维码,然后在后台回复【赚钱】即可。

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

25阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读