Optional 是 Java 8 引进的一个新特性,通常用于缓解常见的空指针异常问题。
Brian Goetz (Java语言设计架构师)对Optional设计意图的原话如下:
Optional is intended to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result," and using null for such was overwhelmingly likely to cause errors.
这句话突出了三个点:
1、Optional 是用来作为方法返回值的
2、Optional 是为了清晰地表达返回值中没有结果的可能性
3、且如果直接返回 null 很可能导致调用端产生错误(尤其是NullPointerException)
Optional 的机制类似于 Java 的受检异常,强迫API调用者面对没有返回值的现实。参透 Optional 的设计意图才能学会正确得使用它。下面介绍一下Optional方法以及围绕这三个点阐述 Optional的最佳实践。
一、Optional的相关方法介绍
1、JDK 提供三个静态方法来构造一个Optional:我们主要记住这个就行了 - Optional.ofNullable(T value)
(1)Optional.of(T value),该方法通过一个非 null 的 value 来构造一个 Optional,返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException。
(2)Optional.ofNullable(T value),该方法和 of 方法的区别在于,传入的参数可以为 null。该方法会判断传入的参数是否为 null,如果为 null 的话,返回的就是 Optional.empty()。
(3)Optional.empty(),该方法用来构造一个空的 Optional,即该 Optional 中不包含值,其实底层实现还是 如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态,然后在 API 层面将 Optional 表现的不能包含 null 值,使得 Optional 只存在 包含值 和 不包含值 两种状态。
2、 ifPresent —— 如果 Optional 中有值,则对该值调用 consumer.accept,否则什么也不做。
3、orElse —— 如果 Optional 中有值则将其返回,否则返回 orElse 方法传入的参数。
4、orElseGet —— 与 orElse 方法的区别在于,orElseGet 方法传入的参数为一个 Supplier 接口的实现 —— 当 Optional 中有值的时候,返回值;当 Optional 中没有值的时候,返回从该 Supplier 获得的值。
User user = Optional.ofNullable(getUserById(id))
.orElse(new User(0, "Unknown"));
User user = Optional.ofNullable(getUserById(id))
.orElseGet(() -> new User(0, "Unknown"));
5、orElseThrow —— 与 orElse 方法的区别在于,orElseThrow 方法当 Optional 中有值的时候,返回值;没有值的时候会抛出异常,抛出的异常由传入的 exceptionSupplier 提供。
User user = Optional.ofNullable(getUserById(id))
.orElseThrow(() -> new EntityNotFoundException("id 为 " + id + " 的用户没有找到"));