Optional 的使用详解
一、Optional 介绍
Optional 被定义为一个简单的容器,它可以保存类型 T 的值,其值可能是 null 或者不是 null。在 Java 8 之前一般某个函数应该返回非空对象但是偶尔却可能返回了 null,而在 Java 8 以后,不推荐你返回 null 而是返回 Optional。
二、Optional 用法
从方法作用来划分,主要可以分为:构建类方法,获取类方法,判断类方法,过滤类方法,映射类方法
1.构建类方法
Optional.of(T t)
: 创建一个 Optional 实例,t 必须非空;Optional.empty()
: 创建一个空的 Optional 实例Optional.ofNullable(T t)
:t 可以为 null
2.获取类方法
T get(): 如果调用对象包含值不为 null,返回该值,否则抛异常
T orElse(T other) :如果有值则将其返回,否则返回指定的 other 对象。
T orElseGet(Supplier<? extends T> other) :如果有值则将其返回,否则返回由 Supplier 接口实现提供的对象。
T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果有值则将其返回,否则抛出由 Supplier
3.判断类方法
boolean isPresent()
: 判断是否包含对象void ifPresent(Consumer<? super T> consumer)
:如果有值,就执行 Consumer 接口的实现代码,并且该值会作为参数传给它。void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) :如果有值,就执行 Consumer 接口的实现代码,并且该值会作为参数传给它,否则执行 Runnable 接口的实现代码。
4.过滤类方法
Optional<T> filter(Predicate<? super <T> predicate)
:如果值存在,并且这个值匹配给定的 predicate,返回一个 Optional 用以描述这个值,否则返回一个空的 Optional。
5.映射类方法
<U>Optional<U> map(Function<? super T,? extends U> mapper):如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的 Optional 作为 map 方法返回值,否则返回空 Optional。
<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper):如果值存在,就对该值执行提供的 mapping 函数调用,返回一个 Optional 类型的值,否则就返回一个空的 Optional 对象
三、源码解析及示例
Optional 代码结构
示例代码
1、创建 Optional 对象
1.Optional.of(T t)
示例
2.Optional.empty()
3.Optional.ofNullable(T value)
4.示例测试
2、获取类方法
1.Optional.get()
2.Optional.orElse(T other)
3.Optional.orElseGet(Supplier<? extends T> other)
4.Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
5.or(Supplier<? extends Optional<? extends T>> supplier)
6.示例代码
3、判断类方法
1.Optional.isPresent()
2.Optional.ifPresent(Consumer<? super T> consumer)
3.Optional.ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
4.示例代码
public void ifTest03(){Trade trade = Trade.builder ().iCode ("qyz0711").iName ("青衣醉 0711").iType ("0711").build ();Trade defaultTrade = Trade.builder ().iCode ("MR1016").iName ("默认值").iType ("1016").build ();Optional<Trade> tradeInfoEmptyOpt = Optional.empty();Optional<Trade> tradeInfoOpt = Optional.of(trade);// 1、isPresent()-> 判断是否存在对象,我们在调用 get 之前,一定要先调用 isPresent,因为直接如果 value 是 null,直接调用 get 会报异常;if (tradeInfoEmptyOpt.isPresent ()) {Trade trade1 = tradeInfoOpt.get ();System.out.println ("isPresent():"+trade1);}else {System.out.println ("isPresent(): null");}//2、ifPresent(Consumer<? super T> consumer)->如果存在值,则使用该值执行给定的操作,否则不执行任何操作。tradeInfoOpt.ifPresent (trade2 -> {System.out.println("ifPresent(Consumer<? super T> consumer):"+trade2);});
4、过滤类方法
1.Optional<T> filter(Predicate<? super <T> predicate)
2.示例代码
5.映射类方法
1.<U>Optional<U> map(Function<? super T,? extends U> mapper)
2.<U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)
3.map 与 flatmap 的区别及示例代码
相同点:两个方法的返回值都是 Optional 对象!
不同点:区别在于调用两个方法需要的传入参数(函数式接口)的返回值不同,
map 方法会自动将入参中的函数式接口返回值包装成 Optional 对象,而 flatMap 方法则要求入参中的函数式接口返回值本身就是 Optional 对象。
入参的不同也就导致了使用场景的不同,如果函数式接口返回值本身就是 Optional 对象,那么就可以直接使用 flatMap 方法,否则就应该使用 map 方法,省去了使用 Optional 包装的麻烦。
比如示例中 toString 返回值是 String 类型,那么此时使用 map 方法更合理。
版权声明: 本文为 InfoQ 作者【echoes】的原创文章。
原文链接:【http://xie.infoq.cn/article/99383fd2bff1f7daa56b585f2】。文章转载请联系作者。
评论