Java8新特性 - Optional的正确打开方式

Louis2019-11-25Java技术JavaJava8

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支持按上述方式级联调用。

其他注意事项

  1. Optional不应该作为方法的入参或类属性
  2. Optional类型不可以被序列化
Last Updated 2024/11/24 20:50:53