一、背景介绍
NullPointerException,中文名:空指针异常,也简称 NPE,是软件系统中最常见的错误异常之一。
很久以前 Google Guava 项目引入了Optional作为解决空指针异常的一种方式,不赞成写过多的代码来显式检查null,以期望程序员写出整洁同时可读性更高的代码。
受 Google Guava 的影响,Optional 现在也成为了Java 8 及以上库代码的一部分。
在介绍Optional技术之前,我们不禁会发出一个疑问:为什么谷歌不赞成写过多的代码来显式检查null?
下面是某个常见的参数判空代码,样例如下。
这还是最普通的三层判断,假如有很大一段业务逻辑处理的时候,你会发现代码不光看起来很臃肿,并且难以阅读,可读性很差!
如果调整为使用Optional来编写的话,可以转换成如下写法:
采用Optional来编程之后,整个代码的可读性和整洁度,是不是要干净很多!
这也是为什么推荐大家使用Optional的原因啦!
当然废话也不多说,代码直接撸起来!
二、案例实践
在 JDK8 中,Optional 共有 12 个核心方法,下面我们一起来看看他们的用法!
2.1、empty()
empty 方法返回一个不包含值的 Optional 实例,单独使用没什么意义,主要和其他方法搭配使用。
2.2、of()
of 方法会返回一个 Optional 实例,如果传入的值非空,会返回包含指定值的对象;如果传入空,会立刻抛出空指针异常。
2.3、ofNullable()
ofNullable 方法会返回一个 Optional 实例,如果传入的值非空,会返回包含指定值的对象;如果传入空,会返回不包含任何值的 empty 对象,也就是最开始介绍的Optional.empty()对象。
2.4、isPresent()
isPresent 方法用来判断实例是否包含值,如果包含非空值,返回 true,否则返回 false。
2.5、get()
get 方法,如果实例包含非空值,则返回当前值;否则抛出 NoSushElementException 异常。
2.6、ifPresent()
ifPresent 方法作用是当实例包含非空值时,执行传入的 Consumer,比如调用一些其他方法;如果包含的值为空,不执行任何操作。
2.7、filter()
filter 方法用于过滤不符合条件的值,接收一个Predicate参数,如果符合条件,会返回当前的Optional实例,否则返回 empty 实例。
2.8、map()
map 方法是链式调用避免空指针的核心方法,当实例包含值时,对值执行传入的Function函数接口方法,并返回一个代表结果值新的Optional实例,也就是将返回的结果再次包装成Optional对象。
2.9、flatMap()
flatMap 方法与 map 方法类似,唯一不同的地方在于:需要手动将返回的值,包装成Optional实例,并且参数值不允许为空。
2.10、orElse()
orElse 方法作用是如果实例包含非空值,那么返回当前值;否则返回指定的默认值。
2.11、orElseGet()
orElseGet 方法作用是如果实例包含非空值,返回这个值;否则,它会执行作为参数传入的Supplier函数式接口方法,并返回其执行结果。
2.12、orElseThrow()
orElseThrow 方法作用是如果实例包含非空值,返回这个值;否则,它会执行作为参数传入的异常类。
三、小结
以上就是 JDK8 新增的Optional类的常用方法总结,其中ofNullable、map和orElse方法搭配使用的最多。
另外orElse、orElseGet、orElseThrow区别如下:
- orElse:如果实例包含空值,返回传入指定的值
- orElseGet:如果实例包含空值,返回传入的方法中返回值
- orElseThrow:如果实例包含空值,返回指定的异常类型
在实际使用的时候,还得结合具体的场景进行合理选择,有时候并不是全部采用Optional来解决NPE异常代码才更加优雅,比如当前对象比较简单,就是一个简单判断,通过obj != null足以解决问题。
因此在保证业务功能的正确和稳定性的基础之上,适当的选择相关的工具来优化代码的整洁度和可读性,更能发挥出锦上添花的效果!