使用Optional
支持没有结果的方法
简单的来说,Optional
是一个包装类,Optional<T>
是引用包装类,还有OptionalInt
, OptionalLong
, OptionalDouble
值包装类。不同于经典的包装类Integer
, Long
, Double
等,Optional
可以为空(此空非彼空null
,更类似于void
,意思没有任何值)。
如果你需要一种机制返回空(没有值),并且返回null
会导致NullPointerException
异常,这样的话你可以考虑使用Optional
。
创建Optional
对象
有三个工厂方法(OptionalInt
, OptionalLong
, OptionalDouble
只有2个工厂方法)
-
创建一个空的
Optional.empty()
-
包装一个非
null
值对象Optional.of()
,如果为null
会抛出NullPointerException
-
包装任何对象包括
null``Optional.ofNullable()
,如果你包装了null
,就类似于Optional.empty()
打开Optional
对象
有几种方法访问包装的元素。你可以直接访问或者通过类似stream流的方式map()
, flatMap()
, filter()
, forEach()
除非你明确知道Optional
中有值,否则你应该避免直接打开它,因为直接打开空Optional
会抛出NoSuchElementException
异常。
你应该先测试是否存在值。有2种方法可以使用isPresent()
和jdk11新增的isEmpty()
然后再打开Optional
,使用如下方法
-
get()
已经废弃,方法名类似getter但会抛出NoSuchElementException
异常 -
orElseThrow()
jdk10推荐模式,与get()
一样 -
orElseThrow(Supplier exceptionSupplier)
指定抛出自定义异常
你也可以给定个默认值,当Optional
为空时返回给定的值
-
orElse(T returnedObject)
-
orElseGet(Supplier<T> supplier)
最后你也可以当Optional
为空时创建另一个Optional
or(Supplier<Optional> supplier)
当Optional
不为空时返回,如果Optional
为空时则创建另一个Optional
并返回
处理Optional
对象
Optional
类提供了类似Stream API的方法更容易与Stream API集成
example
String findCustomerNameById(int id){
List<Customer> customers = ...;
return customers.stream()
.filter(customer->customer.getId() == id);
.findFirst()
.map(Customer::getName)
.orElse("UNKNOWN");
}
消费Optional
上下文
-
ifPresent(Consumer consumer)
-
ifPresentOrElse(Consumer consumer, Runnable runnable)
正确使用Optional
的一些规则
-
切勿将
null
用于Optional
变量或返回值。 -
除非您确定
Optional
不为空,否则切勿调用orElseThrow()
或get()
-
选用
get()
的替代方法,isPresent()
,orElseThrow()
-
测试时不要创建
Optional
-
不要在字段、方法参、集合和映射种使用
Optional
,最好只用于返回值 -
不要使用
Optional
对象的身份操作,例如equals()
,hashCode()
,wait()
等Object
对象方法 -
请记住
Optional
不支持序列化