import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; /** * 一個容器對象,可能會或可能不會包含一個非空值。 * 若是一個值是存在的, {@code isPresent()} will return {@code true} and * {@code get()} will return the value. * @since 1.8 */ public final class Optional<T> { /** * 用於方法empty() */ private static final Optional<?> EMPTY = new Optional<>(); /** * 若是非空值,就是該值;若是爲空,表示沒有值 */ private final T value; /** * 私有化空參構造 * * @implNote 通常只有一個空的實例, {@link Optional#EMPTY}, * 每一個VM應該存在。 */ private Optional() { this.value = null; } /** * 返回一個空的 {@code 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> 無參 * @return 返回一個Optional對象 {@code Optional} */ public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } /** * 私有化有參構造 * * @param value 當前值不能爲null * @throws NullPointerException 若是值爲null,拋出NPE異常 */ private Optional(T value) { //校驗是否對象是否爲空,爲空拋出異常,不爲空(返回傳入的對象) this.value = Objects.requireNonNull(value); /* * public static <T> T requireNonNull(T obj) { * if (obj == null){ * throw new NullPointerException(); * } * return obj; * } * */ } /** * 參數不能爲null * @param <T> the class of the value * @param value 必須非null * @return an {@code Optional} with the value present * @throws NullPointerException if value is null */ public static <T> Optional<T> of(T value) { return new Optional<>(value); } /** * 若是傳入的值爲null,就調用empty()方法,返回一個對象,不然調用of(value)方法,返回一個對象 * @param <T> the class of the value * @param value the possibly-null value to describe * @return an {@code Optional} with a present value if the specified value * is non-null, otherwise an empty {@code Optional} */ public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } /** * 若是存在一個值{ @code Optional},返回值, * 不然 throws {@code NoSuchElementException}. * 此方法不經常使用 * User user = new User(); * Optional userOptional = Optional.ofNullable(user); * Object o1 = userOptional.get(); * //com.shilvfei.web.User@19f2327 * System.out.println(o1); * @return the non-null value held by this {@code Optional} * @throws NoSuchElementException if there is no value present * * @see Optional#isPresent() */ public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; } /** * 判斷值是否爲空,爲空返回false,不爲空返回true * User user = new User(); * Optional userOptional = Optional.ofNullable(user); * //true * System.out.println(userOptional.isPresent()); * @return {@code true} if there is a value present, otherwise {@code false} */ public boolean isPresent() { return value != null; } /** * 若是value != null,調用指定的Consumer實現類中的accept(value)方法, * 不然什麼都不作。 * * @param consumer block to be executed if a value is present * @throws NullPointerException if value is present and {@code consumer} is * null */ 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(); } public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { //判斷對象是否爲空 Objects.requireNonNull(mapper); //若是value爲空,返回Optional對象 if (!isPresent()) return empty(); else { //不爲空,返回mapper.apply(value)的值 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,不爲空返回value {@code other}. * * @param other the value to be returned if there is no value present, may * be null * @return the value, if present, otherwise {@code other} */ public T orElse(T other) { return value != null ? value : other; } /** * 判斷value是否爲空,爲空調用指定方法,並返回該調用方法返回的結果,不爲空返回value的值 * * @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(); } } @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); } @Override public int hashCode() { return Objects.hashCode(value); } @Override public String toString() { return value != null ? String.format("Optional[%s]", value) : "Optional.empty"; } }