Java8新特性 - Optional的正确打开方式
原创2019/11/25...大约 3 分钟
Optional类
java.util.Optional类是Java8新增的容器类,可以保存包含null在内的任意对象。Optional类可以优雅地解决空指针异常。
Optional中常用的几个方法:
| 方法 | 描述 |
|---|---|
| static <T> Optional<T> empty() | 返回空的 Optional 实例。 |
| static <T> Optional<T> of(T value) | 返回一个指定非null值的Optional。 |
| static <T> Optional<T> ofNullable(T value) | 如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 |
| boolean isPresent() | 如果值存在则方法会返回true,否则返回 false。 |
| void ifPresent(Consumer<? super T> consumer) | 如果值存在则使用该值调用 consumer , 否则不做任何事情。 |
| T get() | 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException |
| Optional<T> filter(Predicate<? super <T> predicate) | 如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。 |
| <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper) | 如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional |
| <U>Optional<U> map(Function<? super T,? extends U> mapper) | 如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 |
| T orElse(T other) | 如果存在该值,返回值, 否则返回 other。 |
| T orElseGet(Supplier<? extends T> other) | 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。 |
| <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) | 如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 |
例1:Optional的错误用法
先来看看在Java8之前是如何进行对象判空的:
public static void wrongUseOfOptional(User user) {
String username;
if (user != null) {
// 判断user不为空
username = user.getName();
} else {
username = "anonymous";
}
System.out.println(username);
}替换成Optional对象:
public static void wrongUseOfOptional(User user) {
String username;
// 初始化一个Optional对象
Optional<User> o1 = Optional.ofNullable(user);
if (o1.isPresent()) {
// 判断user不为空
username = o1.get().getName();
} else {
username = "anonymous";
}
System.out.println(username);
}但明眼人一看就知道,以上代码和不使用Optional并无区别,甚至还多了一个初始化操作。因此直接调用isPresent()或get()是不正确的!
例2:Optional的正确用法
public static void rightUseOfOptional(User user) {
Optional<User> o2 = Optional.ofNullable(user);
String username = o2.map(User::getName).orElse("anonymous");
System.out.println(username);
}如上面代码所示,引入Optional后,完全不需要对入参进行判空。首先调用map方法获取name字段,如果user为空,map将会返回一个空的Optional对象;即便user不为空,其name字段也可能为空,因此调用orElse方法,当name为空时返回一个默认的字符串。
当对象存在多层嵌套时,Optional支持按上述方式级联调用。
其他注意事项
- Optional不应该作为方法的入参或类属性
- Optional类型不可以被序列化