Optional到底是个啥
我们在开发中经常会遇到NullPointerException的情况,为了避免出现空指针异常的情况,我们常常需要进行一些防御性的检查如:if(obj != null)这样的判断,虽然可以避免这类问题,但是频繁的if语句让代码显得不够简洁清爽。
作为新时代的程序猿,只有代码码的清爽怡人,整整齐齐,review代码时才能做到随心所欲的装X。于是JDK1.8的一些新特性给了我们一些启发…
首先,什么是Optional类?
Optional是一个包含或着不包含一个非空值的容器对象。它是JDK1.8中,java为我们提供以省略掉繁琐的非空判断,Optional的功用很强大下面是它提供的主要方法:
Optional类的方法结构那么Optional到底能为我们清爽的代码做到什么程度呢?
User小张有话要说:
12岁的小张,大脑经常出现异常情况我们看到小张才刚满12岁,就忘记了自己的家庭住址。于是乎当他自我介绍的时候,大脑发出了空指针异常警报!
小张的大脑发出异常报警一般为了避免这种情况我们需要一些if的骚操作:
1.8之前 我们诸如此作一个自我介绍就匡匡写了七八行。业务复杂点的话就很难受了。那么JDK1.8的时代我们用Optional如何做到风骚走位呢?
我们先来获得一个Optional类——其法有三:
api提供了三种方法获取类empty()方法可以返回一个Optional容器,Optional没有装载着对象。
of(T)方法返回一个Optional容器,但是传入的对象不可以为null,否则将抛出NullPointerException
ofNullable(T)方法,返回一个Optional容器,而且传入的对象可以为null。如果为null则返回一个没有装载对象的Optional容器
三种示例所以当对象为null的时候我们使用of()方法并没有摆脱空指针异常,但是在不确定对象是否为null的时候,我们可以使用ofNullable()方法来避开创建容器的时候出现的异常。
拿到Optional容器后可以用get()方法来获取容器里的value;
但是值为null的时候调用get()方法一样会抛出异常,所以在获得Optional容器后如何判断获得的容器是否为空呢?也就是说我们的对象到底存不存在呢?
Api为我们提供了两种方法isPresent()方法:如果值存在则isPresent()方法会返回true否则返回false;
示例ifPresent()方法:如果值存在则使用该值调用 consumer , 否则不做任何事情:
只有opt1是存在的,所以只有opt里的表达式执行了 只有opt1执行了表达式如何避免异常,还有方法是可以返回默认值的,api为我们提供了三种方法
命名可以看出,就是变异的if()else()判断orElse():它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值:
如果user2是null则返回user3的对象这里user2对象是空的,所以返回了作为默认值的user3。如果user2对象的初始值不为null那么默认值就会被忽略。
还有同类型的 API 是orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的Supplier(供应者) 函数式接口,并将返回其执行结果:
返回的是函数式接口的value乍看起来两个方法是一样的,但细细分析下来的话:
user1为null的情况下 输出结果 当参数都不为null的情况 只有一个执行了getUser()方法对比上面几张图不难发现,无论值为不为空,走不走默认值,orElse()方法里作为返回默认值的getUser()方法都会执行,而orElseGet()方法则没有执行创建操作。
不光能返回默认的值,当传入值为空的时候 还可以自定义异常抛出来:
orElseThrow()—— 它会在对象为空的时候抛出异常,而不是返回备选的值:
值转换:
如果创建的Optional容器中的值存在,对该值执行提供的Function函数调用
map() 对值调用作为参数的函数,然后将返回的值包装在 Optional 中。这就使对返回值进行链试调用的操作成为可能 —— 这里的下一环就是 orElse()。
User类中有一个返回Optional容器的方法
user类中定义的方法 flatMap()方法调用返回值为optional对象的方法可见,在对 User 的Optional 对象调用 flatMap() 时,用它作为参数。其返回的值是解除包装的 String 值
可见map中获取的返回值自动被Optional包装,即返回值 -> Optional<返回值>
flatMap()中返回值保持不变,但必须是Optional类型,即Optional<返回值> -> Optional<返回值>
过滤值
filter() 接受一个Predicate(函数式接口) 参数,返回测试结果为 true 的值。如果测试结果为 false,会返回一个空的 Optional 如下:
user1为空对象,user为小张还可以用来校验参数的合法性:
user1为空对象,getName()肯定为null 抓捕抛出的自定义异常,进行处理Optional 类的链式方法
充分使用Optional,我们可以链接组合他的大部分方法,称为链式调用,可以很方便的解决最开始咱们提到的,对于空指针的判断问题:
传统写法用很多if语句来避免空指针使用optional类的链式调用后改为:
代码清爽多了
网友评论