Java 8 Optional——避免空指针异常的小工具
函数式接口(行为参数化)、Stream、Optional是独立的三个部分,在Java中,他们却能组成一个漂亮的三重奏。函数式接口本身限制很大,它就像天生为Stream设计的,而Optional也是Stream处理终端操作结果的一个重要方式。
创建Optional
Optional.empty()
,创建空OptionalOptional.of(value)
,包装value到Optional内部,如果强行传null的话,汇报NullPointerExceptionofNullable(value)
,同上,但是可以传递null,这样会生成Optional.empty
获取元素
Optional本身是一个包装类,如果按照它的API合理操作,可以避免空指针异常问题.
if (optString.isPresent()){
ostString.get();
}else{
//....
}
便捷函数
除了上面最基本的套路——先验证再取值的方式,还有一些方法可以将两步合一步的方式。
- ifPresent(Consumer
),如果值存在就调用Consumer消费,否则什么也不做 - orElse(otherObj),如果存在就get,否则返回otherObj
- orElseGet(Supplier),如果存在就get,否则返回Supplier的生成对象
- orElseThrow(Supplier),存在就get,否则返回Supplier生成的异常
其他的都是显而易见的,对于生成异常,这里有个示例,
optString.orElseThrow(()->new Exception("supplier"));
返回Optional的流操作
主要有
- findFirst
- findAny
- max
- min
- reduce
- IntStream等数字Stream,使用的average
对象方法
filter(PredicateOptional.empty()
示例代码OptionalFilter.java
map(Function<T,R>),将Optional内部的值通过Function转化,返回包装结果的Optional;如果内部value为空,则返回Optional.empty()
。
示例代码OptionalMap
flatMap(Function<T,R>),与map一样,提取Optional内部的值,进行转化。不同的是,它不会自动将value包装进Optional,这一点需要调用者自己提供能够返回Optional的Function。
示例代码OptionalFlatMap.java
处理Optional流
所谓Optional流,就是元素为Optional类型的Stream,当我们想处理null值的时候,自然会想到Optional
。
将普通的流转化成Optional,
Stream.generate(Signal::morse)
.map(signal->Optional.ofNullable(signal));
这里的Signal::morse是普通Supplier函数。(注意当使用::
的时候,jvm会自动根据函数签名,将其包装成Supplier对象,不需要函数显示的实现Supplier接口)。
消费Optional流,
optSingnalStream.limit(10)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(System.out::println);
首先通过filter
过滤掉空值,再通过map选出包装value。如果不这么做,直接打印的话,是一个个Optional对象,而不是其内包含的值。
示例代码StreamOfOptionals.java