Optional源码解析

2019-08-19  本文已影响0人  拾月初六

1.成员变量

 /**
     * Common instance for {@code empty()}.
     */
    private static final Optional<?> EMPTY = new Optional<>();

    /**
     * If non-null, the value; if null, indicates no value is present
     */
    private final T value;

1.1 EMPTY做为一个空值的常量用于静态创建一个空的Optional对象

1.2 value用来存储Optional对象中实际的值

2.构造方法

/**
     * Constructs an empty instance.
     *
     * @implNote Generally only one empty instance, {@link Optional#EMPTY},
     * should exist per VM.
     */
    private Optional() {
        this.value = null;
    }

2.1 第一个私有的无参构造方法,外界无法访问使用

/**
     * Returns an empty {@code Optional} instance.  No value is present for this
     * Optional.
     *
     * @apiNote Though it may be tempting to do so, avoid testing if an object
     * is empty by comparing with {@code ==} against instances returned by
     * {@code Option.empty()}. There is no guarantee that it is a singleton.
     * Instead, use {@link #isPresent()}.
     *
     * @param <T> Type of the non-existent value
     * @return an empty {@code Optional}
     */
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

2.2 静态方法empty会返回EMPTY常量的Optional对象,里面的value值为空

/**
     * Constructs an instance with the value present.
     *
     * @param value the non-null value to be present
     * @throws NullPointerException if value is null
     */
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

2.3 私有的有参构造,外界无法访问,提供给本类的静态方法,用于创建value有值的Optional对象,注意此处调用了 Objects.requireNonNull方法,也就意为着如果此时传入的value值为空,会抛出一个空指针异常。

3.方法说明

3.1 of和ofNullable方法

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

    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

这两个方法都会使用传入的value调用有参构造,不过如果value为null的时候,of方法会抛出空指针异常,而ofNullable方法会判断value为null后,返回空的Optional对象,所以一般为了安全性,我们都是使用后面一个方法。

3.2 get方法

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

这是获取对象中value值的方法,可以看到,如果value是一个null值,此时会抛出一个异常。

3.3 isPresent

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

此方法返回对象中value值是否为null的判断,一般搭配上面一个get方法使用,先判断是否为空,不为空的话再调用get方法获取value值。

3.4 ifPresent

public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

此方法会先判断value是否为空,为空的话,则没有任何操作,不为空的话,则用传入的函数消费value值。


此处可看到o2里面有值,所以被消费了。

3.5 filter

public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

filter会先判断传入的predicate 断言是否为空,为空的话则抛出空指针异常,不为空的话接着判断value值是否为空,为空,则直接返回这个空的Optional对象,不为空接着用断言测试value值,通过返回这个对象,不通过则调用empty方法,返回一个value为空的Optional对象。

public static void main(String[] args) {
        Optional<String> o1 = Optional.ofNullable(null);
        Optional<String> o2 = Optional.ofNullable("hello world");
        /* 断言为空 */
        try {
            Optional<String> filter1 = o2.filter(null);
            System.out.println("第一个"+filter1.isPresent());
        } catch (Exception e) {
            e.printStackTrace();
        }
        /* value为空 */
        Optional<String> filter2 = o1.filter(StringUtils::isEmpty);
        System.out.println("第二个"+filter2.isPresent());
        System.out.println("value为空,返回的就是此时的空对象"+ (o1 == filter2));
        /* 断言不通过 */
        Optional<String> filter3 = o2.filter(StringUtils::isEmpty);
        System.out.println("第三个"+filter3.isPresent());
        /* 断言通过 */
        Optional<String> filter4 = o2.filter(StringUtils::isNotEmpty);
        System.out.println("第四个"+filter4.isPresent());
        System.out.println("value为空,返回的就是此时的空对象"+ (o2 == filter4));
    }

运行代码得到



此时可以得知
1:断言为空,报空指针异常
2:value为空会返回传入的空对象
3:断言不通过,会返回一个新的空对象
4:断言通过,返回传入的对象

3.6 map

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }

map方法也是先判断传入的函数是否为空,然后判断value是否为空,最后将函数应用于value值,并返回应用转化完后的值生成的Optional对象。

public static void main(String[] args) {
        Optional<String> o1 = Optional.ofNullable(null);
        Optional<String> o2 = Optional.ofNullable("hello world");
        /* 应用为空 */
        try {
            Optional<String> map1 = o2.map(null);
            System.out.println("第一个"+map1.isPresent());
        } catch (Exception e) {
            e.printStackTrace();
        }
        /* value为空 */
        Optional<Integer> map2 = o1.map(String::length);
        System.out.println("第二个"+map2.isPresent());
        /* 断言不通过 */
        Optional<Integer> map3 = o2.map(String::length);
        System.out.println("第三个"+map3.get());
    }

此时可以得知
1:传入的函数为空,报空指针异常
2:value为空会返回传入的空对象
3:map方法会把原来的Optional转换成另外一个Optional,转换后的泛型取决于函数应用后返回的类型。

3.7 flatMap

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }

flatMap与map方法类型,但是有一个很大的区别是flatMap是一个扁平化操作,也就是将可以将多个flatMap连接起来,而map则不行。
这里比较复杂,本人也是查看数据慢慢理解的,避免解释错误,直接上图。



一般来说。我们可以用flatMap用于多层级的属性获取,例如

public static void main(String[] args) {
        Apple a1 = new Apple();
        a1.setColor("red");
        Optional<Apple> optional = Optional.ofNullable(a1);
        /*map方法返回的是返回对象上面再封装一层Optional的对象*/
        Optional<Optional<String>> map = optional.map(apple->getColor(apple));
        /*flatMap方法会将多层Optional转换成一层*/
        Optional<String> map2 = optional.flatMap(a->getColor(a));
        /*示例 如果要获取某个苹果的颜色对应字符串的长度*/
        optional.flatMap(apple->getColor(apple)).map(String::length);
        /*第二个方法会编译报错 因为此时第二个map操作的对象是Optional<String>类型 自然没有length方法 */
        optional.map(apple->getColor(apple)).map(String::length).map(String::length);
    }
    
    public static Optional<String> getColor(Apple apple) {
        return Optional.ofNullable(apple.getColor());
    }

这个例子中我们就可以先通过flatMap获取颜色的Optional的对象,在获取颜色String的长度。

3.8 orElse

public T orElse(T other) {
        return value != null ? value : other;
    }

获取value的值,当value是null的时候,返回给定的默认值other


例子中o1因为value有值,所以打印的是value的值hello
o2因为没值,所以打印的是默认值unknown

3.9 orElseGet

此方法和orElse类似,不过使用函数替代了直接的默认值对象

3.10 orElseThrow

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

此方法是,当value为null的时候,抛出传入的指定的异常


4 其他方法

剩下的三个方法是Object通用的equals,hashCode,toString方法,就不再赘述了。

上一篇 下一篇

猜你喜欢

热点阅读