一、背景
程序员写代码经常被调侃为 “写BUG”。
然而开发中遇到的其中一个主要 BUG 就是 空指针造成的。
很多人并不会认为预发空指针有多难,甚至有些人会认为自己如果写代码肯定会注意到。
最大的问题是,我们写代码时很多空指针的情况并不是直接发生的,而是被“传递”过来的,导致没有留意。
下面介绍几种工作中可能不经意中写出的,花式踩坑空指针异常的姿势。
二、踩坑姿势
2.1 自动拆箱空指针异常
如调用类似下面这种格式的二方服务接口,
如果不进行判空而直接使用,则很容易碰到空指针:
正确的使用姿势应该是:
2.2 RPC接口返回null
二方服务的批量查询接口如果数据量大容易超时,因此我们可以分批查询,参加下面代码:
看似没啥问题,先将参数集合拆分成 多个小集合,然后调用传入的接口查询。
问题是,如果其中一批调用返回了 null 会怎样?
很可能发生空指针异常。
因此在合并前应该将结果为 null 的过滤掉。
三、预防
3.1 手册
《阿里巴巴 Java编程规范》 给出了空指针的一些常见场景:
返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE
数据库查询结果可能为null
集合元素即使 isNotEmpty,取出数据元素可能为null
远程调用返回对象时,一律要求进行空指针判断,防止 NPE
对于 Session 中获取的数据,建议进行 NPE 检查,避免空指针
级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE
3.2 源码
Java 空指针异常的源码注释提供了 产生空指针的主要原因:
即
调用 null 对象的实例方法
访问或者修改 null 对象的属性
获取值为null 的数组长度
访问或修改值为 null 的二维数组的列
把 null 当做 Throwable 对象抛出
官方源码列举的几种情况,更全面,更有参考价值。
四、预发空指针
4.1 作为接口提供方或者编写者
编写接口时
如果返回值为集合类型,如果没值尽量返回空集合。
可以返回Optional
4.2 作为接口的使用方
使用 commons-lang3 或者 guava的 字符串、对象、集合工具类判空
使用@Nonnull 注解等避免必传字段前端传null
五、总结
写代码时不要想当然,很多时候大意失荆州。
要了解常见的造成空指针的场景,开发时极力避免。
多看源码注释,会有更多发现。