Optional到底是个啥
我们在开发中经常会遇到NullPointerException的情况,为了避免出现空指针异常的情况,我们常常需要进行一些防御性的检查如:if(obj != null)这样的判断,虽然可以避免这类问题,但是频繁的if语句让代码显得不够简洁清爽。
作为新时代的程序猿,只有代码码的清爽怡人,整整齐齐,review代码时才能做到随心所欲的装X。于是JDK1.8的一些新特性给了我们一些启发…
首先,什么是Optional类?
Optional是一个包含或着不包含一个非空值的容器对象。它是JDK1.8中,java为我们提供以省略掉繁琐的非空判断,Optional的功用很强大下面是它提供的主要方法:

那么Optional到底能为我们清爽的代码做到什么程度呢?
User小张有话要说:

我们看到小张才刚满12岁,就忘记了自己的家庭住址。于是乎当他自我介绍的时候,大脑发出了空指针异常警报!

一般为了避免这种情况我们需要一些if的骚操作:

一个自我介绍就匡匡写了七八行。业务复杂点的话就很难受了。那么JDK1.8的时代我们用Optional如何做到风骚走位呢?
我们先来获得一个Optional类——其法有三:

empty()方法可以返回一个Optional容器,Optional没有装载着对象。
of(T)方法返回一个Optional容器,但是传入的对象不可以为null,否则将抛出NullPointerException
ofNullable(T)方法,返回一个Optional容器,而且传入的对象可以为null。如果为null则返回一个没有装载对象的Optional容器

所以当对象为null的时候我们使用of()方法并没有摆脱空指针异常,但是在不确定对象是否为null的时候,我们可以使用ofNullable()方法来避开创建容器的时候出现的异常。
拿到Optional容器后可以用get()方法来获取容器里的value;
但是值为null的时候调用get()方法一样会抛出异常,所以在获得Optional容器后如何判断获得的容器是否为空呢?也就是说我们的对象到底存不存在呢?

isPresent()方法:如果值存在则isPresent()方法会返回true否则返回false;

ifPresent()方法:如果值存在则使用该值调用 consumer , 否则不做任何事情:


如何避免异常,还有方法是可以返回默认值的,api为我们提供了三种方法

orElse():它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值:

这里user2对象是空的,所以返回了作为默认值的user3。如果user2对象的初始值不为null那么默认值就会被忽略。
还有同类型的 API 是orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的Supplier(供应者) 函数式接口,并将返回其执行结果:

乍看起来两个方法是一样的,但细细分析下来的话:




对比上面几张图不难发现,无论值为不为空,走不走默认值,orElse()方法里作为返回默认值的getUser()方法都会执行,而orElseGet()方法则没有执行创建操作。
不光能返回默认的值,当传入值为空的时候 还可以自定义异常抛出来:
orElseThrow()—— 它会在对象为空的时候抛出异常,而不是返回备选的值:


值转换:
如果创建的Optional容器中的值存在,对该值执行提供的Function函数调用

map() 对值调用作为参数的函数,然后将返回的值包装在 Optional 中。这就使对返回值进行链试调用的操作成为可能 —— 这里的下一环就是 orElse()。
User类中有一个返回Optional容器的方法


可见,在对 User 的Optional 对象调用 flatMap() 时,用它作为参数。其返回的值是解除包装的 String 值
可见map中获取的返回值自动被Optional包装,即返回值 -> Optional<返回值>
flatMap()中返回值保持不变,但必须是Optional类型,即Optional<返回值> -> Optional<返回值>
过滤值
filter() 接受一个Predicate(函数式接口) 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional 如下:


还可以用来校验参数的合法性:


Optional 类的链式方法
充分使用Optional,我们可以链接组合他的大部分方法,称为链式调用,可以很方便的解决最开始咱们提到的,对于空指针的判断问题:

使用optional类的链式调用后改为:

网友评论