Optional类
引入
NPE
问题就是在开发中经常碰到的NullPointerException
,即空指针问题,Optional
类就是用来优雅解决该问题的方案。
比如大家可能都有这样的经历:调用一个方法得到了返回值却不能直接将返回值作为参数去调用别的方法。我们首先要判断这个返回值是否为null
,只有在非空的前提下才能将其作为其他方法的参数。
以用户类和地址类举例说明其用法:
这种代码可能会出现空指针问题,在实际开发中,如果不使用Optional
类,极其不优雅的处理方式如下:
上面的代码保证了代码的第三行、第五行、第七行肯定不会出现空指针,但是这个代码真的是非常的冗长和丑陋。
java.util
包下面的Optional
类提供了一套API来处理一个对象是否为null
值的问题。
源码解读及各API的使用
部分源码:
其本质是内部有一个泛型容器存储外部需要判断null
值的对象,同时提供了两个私有的构造函数,不能被外部所调用,只能由类内部的函数调用
- 无参数的构造函数提供一个
value=null
的Optional
对象
- 有参数的构造函数提供一个
value
一定不能为null
的Optional
对象,因为它调用了Objects
类的requireNonNull
方法。
of
这是一个静态方法,调用有参数的构造函数,返回的是value
值一定不为null
的Optional
对象,因为有参数的构造方法底层调用了Objects
的requireNonNull
方法,如果传入的value
为null
值,那么一定会报空指针异常。不允许value
为null
,实际开发中不常用。
empty
这是一个静态方法,直接将类初始化时加载的value
为null
的Optional
对象给用户。
ofNullable
这是一个静态方法,代表value
值是可为空的。如果为null
值,那么返回一个value
为null
的Optional
对象;如果不为null
值,那么返回一个value
不为null
的Option
对象。允许value
为null
,实际开发中常用。
与of
的区别:当value
值为null
时,of
会报NullPointerException
异常;ofNullable
不会throw Exception
,ofNullable
直接返回一个EMPTY
对象(value
为null
的Optional
对象)。
::: tip 那是不是意味着,我们在项目中只用ofNullable函数而不用of函数呢?
- 不是的,一个东西存在那么自然有存在的价值。
- 当我们在运行过程中,不想隐藏
NullPointerException
,而是要立即报告,这种情况下就用of
函数。
- 但是不得不承认,这样的场景真的很少。
:::
orElse
这是一个实例方法,会首先判断调用它的Optional
对象中的value
值,如果为不为null
,那么就返回该value
值,如果为null
,就返回传入的other
对象。
orElseGet
该方法与orElse
方法类似,只不过传入的other
对象可以通过一个提供者函数式接口提供,这里可以改成lambda
表达式的形式。为了方便对代码的理解,所以上面写的测试代码稍显复杂,实际开发中可以使用lambda
表达式简化。
orElseThrow
如果value
值不为null
,那么直接返回,如果value
值为null
,可以自定义业务逻辑功能说明语句抛出异常,不影响后续代码执行。
map
如果有值,则对其执行调用mapper
函数得到返回值,将创建包含mapper
返回值的Optional
对象作为map
方法返回值,否则返回空Optional
对象。
map
方法用来对Optional
实例的值执行一系列操作。通过一组实现了Function
接口的lambda
表达式传入操作。
flatMap
如果有值,为其执行mapper
函数返回Optional
对象类型返回值,否则返回空Optional
对象。flatMap
与map
方法类似,区别在于flatMap
中的mapper
返回值必须是Optional
对象。调用结束时,flatMap
不会对结果用Optional
封装。
flatMap
方法与map
方法类似,区别在于mapper
函数的返回值不同。map
方法的mapper
函数返回值可以是任何类型T
,而flatMap
方法的mapper
函数必须是Optional
对象。
filter
如果有值并且满足断言条件返回包含该值的Optional
对象,否则返回空Optional
对象。
isPresent
ifPresent
get
equals
hashCode
toString
使用例子
运行结果:
假设有如下的类层次结构:
解决这种结构的深层嵌套路径是有点麻烦的,我们必须编写一堆null
检查来确保不会导致一个 NullPointerException
。
我们可以通过利用Optional
类型来摆脱所有这些null
检查。map
方法接收一个Function
类型的lambda
表达式,并自动将每个function
的结果包装成一个Optional
对象,这使我们能够在一行中进行多个 map
操作。
使用总结
使用Optional
工具类判断一个对象的NPE
问题,一定要先通过其静态方法(of、empty、ofNullable)
获得Optional
对象,进而通过一些实例方法进行一系列的操作获得最后的对象。
API方法名称 | 用处 |
---|
of | 为非null 的值创建一个Optional 对象。 |
empty | 为null 的值创建一个Optional 对象。 |
ofNullable | 为指定的值创建一个Optional 对象,如果指定的值为null ,则返回一个空的Optional 对象。 |
isPresent | 如果值不为null ,则返回true ,否则返回false 。 |
get | 如果Optional 对象的值并不为空则将其返回,否则抛出NoSuchElementException 。 |
ifPresent | 如果Optional 对象有值(不为空)则为其调用Consumer ,否则不做处理 |
orElse | 如果有值则将其返回,否则返回指定的其它值。 |
orElseGet | orElseGet 方法可以接受Supplier 接口的实现用来生成默认值。 |
orElseThrow | 如果有值则将其返回,否则抛出Supplier 接口创建的异常。 |
map | 如果有值,则对其执行调用mapper 函数得到返回值,并且将创建包含mapper 返回值的Optional 对象作为map 方法返回值,否则返回空Optional 对象。 |
flatMap | 如果有值,为其执行mapper 函数返回Optional 类型返回值,否则返回空Optional 对象。flatMap 与map 方法类似,区别在于flatMap 中的mapper 返回值必须是Optional 对象。调用结束时,flatMap 不会对结果用Optional 封装。 |
filter | 如果有值并且满足断言条件返回包含该值的Optional 对象,否则返回空Optional 对象。 |