Java 8 新特性——Optional

一.Optional 简介

Optional 类是 Java 8 才引入的,Optional 是个容器,它可以保存类型 T 的值,或者仅仅保存null。Optional 提供了很多方法,这样我们就不用显式进行空值检测。Optional 类的引入很好的解决空指针异常。

二.Optional 对象的创建

下面是 Optional 的部分源码,发现它的构造函数是私有的,所以我们不能通过 new 来创建 Optional 对象。同时,我们发现它提供了三个静态的方法,empty、of 和 ofNullable,通过这三个方法可以获取到一个 Optional 对象。

    private static final Optional EMPTY = new Optional<>(null);

    private final T value;

    public static Optional empty() {
        @SuppressWarnings("unchecked")
        Optional t = (Optional) EMPTY;
        return t;
    }

    private Optional(T value) {
        this.value = value;
    }

    public static  Optional of(T value) {
        return new Optional<>(Objects.requireNonNull(value));
    }

    @SuppressWarnings("unchecked")
    public static  Optional ofNullable(T value) {
        return value == null ? (Optional) EMPTY
                             : new Optional<>(value);
    }

三个方法的比较

// 创建一个包装对象为 null 的 Optional
Optional empty = Optional.empty();

// 创建一个包装对象为非 null 的 Optional
// 如果为 null 会报空指针
Optional of = Optional.of("hello");

// 创建一个包装对象可能为 null 的 Optional
// 如果为 null 就等价于 Optional.empty()
Optional ofNullable = Optional.ofNullable(null); 
  

三.Optional 常用方法

1.get 方法

获取 Optional 包装的对象,如果包装的对象为 null,会抛出 NoSuchElementException

public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

2.isPresent 方法

判断 Optional 包装的对象是否为 null

public boolean isPresent() {
    return value != null;
}

3.ifPresent 方法

判断 Optional 包装的对象是否为 null,如果不为 null,则执行 Consumer 的 accept 方法,这个Consumer 是一个函数式接口,可以用 Lambda 表达式实现。

    public void ifPresent(Consumer action) {
        if (value != null) {
            action.accept(value);
        }
    }
    Optional of = Optional.ofNullable("hello");
    // 如果 Optional 包装的为非 null 就会将包装的对象打印出来
    of.ifPresent(System.out::println);

4.ifPresentOrElse 方法

判断 Optional 包装的对象是否为 null,如果不为 null,则执行 Consumer 的 accept 方法,否则就会执行 Runable 的 run 方法

    public void ifPresentOrElse(Consumer action, Runnable emptyAction) {
        if (value != null) {
            action.accept(value);
        } else {
            emptyAction.run();
        }
    }
Optional ofNullable = Optional.ofNullable(null);
ofNullable.ifPresentOrElse(System.out::println, () -> {
    System.out.println("我是一个 null");
}); 
  

5.filter 方法

filter 方法通过 Predicate 判断是否满足条件,如果满足则返回该对象,不满足则返回一个包装 null的 Optional 对象

    public Optional filter(Predicate predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent()) {
            return this;
        } else {
            return predicate.test(value) ? this : empty();
        }
    }
Optional of = Optional.of(1);
// 因为1 < 2,不满足条件,所以这个地方就会返回一个包装 null 的 Optional 对象
Optional integer = of.filter(t -> {
    if (t > 2) {
        return true;
    } else {
        return false;
    }
});

6.map 方法

map 方法首先判断 Optional 包装的对象是否为 null,如果为 null 则返回一个包装 null 的 Optional对象;否则,通过 Function 的 apply 方法运算,获得一个新值包装成一个新的 Optional 对象并返回。

    public  Optional map(Function mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent()) {
            return empty();
        } else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
Optional of = Optional.of(1);
// 给 Optional 包装对象加 1
Optional newOptional = of.map(t -> t + 1);

7.flatMap 方法

与 map 方法相似,只是 map 方法接收的 Function 是 Function

而 flatMap 方法接收的 Function 是 Function,所以apply方法需要返回一个 Optional 对象

    public  Optional flatMap(Function> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent()) {
            return empty();
        } else {
            @SuppressWarnings("unchecked")
            Optional r = (Optional) mapper.apply(value);
            return Objects.requireNonNull(r);
        }
    }
Optional of = Optional.of(1);
// 给 Optional 包装对象加 1
Optional integer = of.flatMap(t -> Optional.of(t + 1));

8.指定默认值的一些方式

    // 如果包装的对象为非 null,则返回 Optional;如果包装对象为 null,则通过 Supplier 构造出一个新的 Optional 返回
    public Optional or(Supplier> supplier) {
        Objects.requireNonNull(supplier);
        if (isPresent()) {
            return this;
        } else {
            @SuppressWarnings("unchecked")
            Optional r = (Optional) supplier.get();
            return Objects.requireNonNull(r);
        }
    }
    
    // 如果包装的对象为非 null 则返回包装对象;如果包装对象为 null,则返回 other
    public T orElse(T other) {
        return value != null ? value : other;
    }

    // 与 orElse 功能一致,只是接收的参数类型不同
    public T orElseGet(Supplier supplier) {
        return value != null ? value : supplier.get();
    }

    
    // 如果包装的对象为非 null 则返回包装对象;如果包装对象为 null,则抛出异常
    public T orElseThrow() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

四.Optional 使用总结

  • Optional 尽量只用作方法的返回类型
  • 调用返回类型为 Optional 的方法后,需要对返回值进行空值判断
  • 适度的使用 Optional,避免降低代码的可读性和性能
  • 充分了解 Optional API 的使用场景,避免为了使用而使用

你可能感兴趣的:(java,开发语言)