Optional

Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

源码:

public final class Optional<T> {
    /**
     * 调用私有的空构造方法
     */
    private static final Optional<?> EMPTY = new Optional<>();

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

    /**
     * 构造方法:构造一个容器值value为空的Optional对象
     */
    private Optional() {
        this.value = null;
    }

    /**
     *静态方法:构造一个容器值value为空的Optional对象
     *如果不为空,则
     */
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    /**
     * 构造方法:构造一个容器值value为入参的Optional对象
     * T value 不能为空(requireNonNull)
     */
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    /**
     * 静态方法:调用私有的有参构造方法,构造一个容器值value为入参的Optional对象
     * T value 不能为空(requireNonNull)
     */
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    /**
     * 二者折中,参数 T value可以为空,也可以不为空,如果为空,则构造一个容器值value为空的Optional对象
     *如果不为空,则构造一个容器值value为入参的Optional对象
     */
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    /**
     *获取容器的value值,如果为空则抛出异常NoSuchElementException
     */
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    /**
     * 判断容易value值
     */
    public boolean isPresent() {
        return value != null;
    }

    /**
     * 如果非空,则执行函数式接口Consumer的accept
     */
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

    /**
     * If a value is present, and the value matches the given predicate,
     * return an {@code Optional} describing the value, otherwise return an
     * empty {@code Optional}.
     *
     * @param predicate a predicate to apply to the value, if present
     * @return an {@code Optional} describing the value of this {@code Optional}
     * if a value is present and the value matches the given predicate,
     * otherwise an empty {@code Optional}
     * @throws NullPointerException if the predicate is null
     */
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    /**
     * 参数是个Function,如果value不存在,调用empty()返回一个值为空的Optional
     * 如果value存在,将Function的apply(value)作为参数执行ofNullable,返回一个新的
     * Optional
     */
    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));
        }
    }

    /**
     * If a value is present, apply the provided {@code Optional}-bearing
     * mapping function to it, return that result, otherwise return an empty
     * {@code Optional}.  This method is similar to {@link #map(Function)},
     * but the provided mapper is one whose result is already an {@code Optional},
     * and if invoked, {@code flatMap} does not wrap it with an additional
     * {@code Optional}.
     *
     * @param <U> The type parameter to the {@code Optional} returned by
     * @param mapper a mapping function to apply to the value, if present
     *           the mapping function
     * @return the result of applying an {@code Optional}-bearing mapping
     * function to the value of this {@code Optional}, if a value is present,
     * otherwise an empty {@code Optional}
     * @throws NullPointerException if the mapping function is null or returns
     * a null result
     */
    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));
        }
    }

    /**
     * 如果value存在则返回,如果不存在则放回入参 other
     */
    public T orElse(T other) {
        return value != null ? value : other;
    }

    /**
     * Return the value if present, otherwise invoke {@code other} and return
     * the result of that invocation.
     *
     * @param other a {@code Supplier} whose result is returned if no value
     * is present
     * @return the value if present otherwise the result of {@code other.get()}
     * @throws NullPointerException if value is not present and {@code other} is
     * null
     */
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

    /**
     * Return the contained value, if present, otherwise throw an exception
     * to be created by the provided supplier.
     *
     * @apiNote A method reference to the exception constructor with an empty
     * argument list can be used as the supplier. For example,
     * {@code IllegalStateException::new}
     *
     * @param <X> Type of the exception to be thrown
     * @param exceptionSupplier The supplier which will return the exception to
     * be thrown
     * @return the present value
     * @throws X if there is no value present
     * @throws NullPointerException if no value is present and
     * {@code exceptionSupplier} is null
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    /**
     * Indicates whether some other object is "equal to" this Optional. The
     * other object is considered equal if:
     * <ul>
     * <li>it is also an {@code Optional} and;
     * <li>both instances have no value present or;
     * <li>the present values are "equal to" each other via {@code equals()}.
     * </ul>
     *
     * @param obj an object to be tested for equality
     * @return {code true} if the other object is "equal to" this object
     * otherwise {@code false}
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Optional)) {
            return false;
        }

        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    }

    /**
     * Returns the hash code value of the present value, if any, or 0 (zero) if
     * no value is present.
     *
     * @return hash code value of the present value or 0 if no value is present
     */
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    /**
     * Returns a non-empty string representation of this Optional suitable for
     * debugging. The exact presentation format is unspecified and may vary
     * between implementations and versions.
     *
     * @implSpec If a value is present the result must include its string
     * representation in the result. Empty and present Optionals must be
     * unambiguously differentiable.
     *
     * @return the string representation of this instance
     */
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

栗子:

public class OptionalTest {
    public static void main(String[] args) {
        Optional<String> opt1=Optional.of("hello"); //value: hello
        System.out.println(opt1.get());
        //Optional<String> opt2=Optional.of(null); //NullPointerException
        //Optional<String> opt3=Optional.empty(); //NullPointerException
        //opt3.get(); //NoSuchElementException("No value present")

        opt1.ifPresent(e-> System.out.println(new StringBuffer(e).append(" world")));//hello world


        //-------------通过Optional避免空指针------------------:
        String s=null;
        Optional<String> opt4=Optional.ofNullable(s);
        //one:
        if (opt4.isPresent()){
            System.out.println(s+": 非空");
        }
        //two:
        opt4.ifPresent(e-> System.out.println(s+": 非空"));


        // orElse 如果value存在则返回,如果不存在则放回入参
        Optional<String> opt5=Optional.empty();
        System.out.println(opt5.orElse("value为空")); //value为空
        Optional<String> opt6=Optional.of("syc");
        System.out.println(opt6.orElse("value为空")); //syc


        // orElseGet 参数是个Supplier
        Optional<String> opt7=Optional.empty();
        String value = opt7.orElseGet(() -> new StringBuffer("value为空").toString());
        System.out.println(value);//value为空
        
        
        //map
        Optional<String> opt8=Optional.of(" ni hao ");
        Optional<String> o = opt8.map(e -> e + "syc");
        System.out.println(o.get());// ni hao syc
    }
}

还有OptionalDouble,OptionalInt,OptionalLong等,基本与Optional大同小异