天天看點

Java8 Optional簡介Optional

簡介

Optional

是一個沒有子類的工具類,是一個可以為null的容器對象,它的主要作用就是用來避免null的檢查,防止出現

NPE

Optional

是個容器:它可以儲存類型T的值,或者僅僅儲存null。

Optional

提供很多有用的方法,這樣我們就不用顯式進行空值檢測。Optional 類的引入很好的解決空指針異常。

public final class Optional<T> {}           

複制

Optional

Opitonal

類就是Java提供的為了解決大家平時判斷對象是否為空用 會用

null != obj

這樣的方式存在的判斷,進而令人頭疼導緻

NPE

(Null Pointer Exception 空指針異常),同時

Optional

的存在可以讓代碼更加簡單,可讀性跟高,代碼寫起來更高效。

源碼

package java.util;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * @since 1.8
 */
public final class Optional<T> {
    /**
     * 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;

    /**
     * 私有構造方法
     */
    private Optional() {
        this.value = null;
    }

    /**
     * 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}
     */
    // 傳回一個空的 Optional執行個體
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    /**
     * 私有構造方法
     */
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    /**
     * Returns an {@code Optional} with the specified present non-null value.
     *
     * @param <T> the class of the value
     * @param value the value to be present, which must be non-null
     * @return an {@code Optional} with the value present
     * @throws NullPointerException if value is null
     */
    // 傳回具有 Optional的目前非空值的Optional
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    /**
     * Returns an {@code Optional} describing the specified value, if non-null,
     * otherwise returns an empty {@code Optional}.
     *
     * @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}
     */
    // 傳回一個 Optional指定值的Optional,如果非空,則傳回一個空的 Optional
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    /**
     * If a value is present in this {@code Optional}, returns the value,
     * otherwise throws {@code NoSuchElementException}.
     *
     * @return the non-null value held by this {@code Optional}
     * @throws NoSuchElementException if there is no value present
     *
     * @see Optional#isPresent()
     */
    // 如果Optional中有一個值,傳回值,否則抛出 NoSuchElementException 。
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    /**
     * Return {@code true} if there is a value present, otherwise {@code false}.
     *
     * @return {@code true} if there is a value present, otherwise {@code false}
     */
    // 傳回true如果存在值,否則為 false
    public boolean isPresent() {
        return value != null;
    }

    /**
     * If a value is present, invoke the specified consumer with the value,
     * otherwise do nothing.
     *
     * @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
     */
    // 如果一個值存在,并且該值給定的謂詞相比對時,傳回一個 Optional描述的值,否則傳回一個空的 Optional
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    /**
     * If a value is present, apply the provided mapping function to it,
     * and if the result is non-null, return an {@code Optional} describing the
     * result.  Otherwise return an empty {@code Optional}.
     *
     * @apiNote This method supports post-processing on optional values, without
     * the need to explicitly check for a return status.  For example, the
     * following code traverses a stream of file names, selects one that has
     * not yet been processed, and then opens that file, returning an
     * {@code Optional<FileInputStream>}:
     *
     * <pre>{@code
     *     Optional<FileInputStream> fis =
     *         names.stream().filter(name -> !isProcessedYet(name))
     *                       .findFirst()
     *                       .map(name -> new FileInputStream(name));
     * }</pre>
     *
     * Here, {@code findFirst} returns an {@code Optional<String>}, and then
     * {@code map} returns an {@code Optional<FileInputStream>} for the desired
     * file if one exists.
     *
     * @param <U> The type of the result of the mapping function
     * @param mapper a mapping function to apply to the value, if present
     * @return an {@code Optional} describing the result of applying a 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
     */
    // 如果存在一個值,則應用提供的映射函數,如果結果不為空,則傳回一個 Optional結果的 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
     */
    // 如果一個值存在,應用提供的 Optional映射函數給它,傳回該結果,否則傳回一個空的 Optional 。
    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));
        }
    }

    /**
     * Return the value if present, otherwise return {@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;
    }

    /**
     * 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";
    }
}           

複制

構造

建立

Optional

對象有三種方法:

empty()

of()

ofNullable()

,均為靜态方法。

如果

Optional

對象沒有值則用

empty()

方法。

//建立一個包裝對象值為空的Optional對象
Optional optional = Optional.empty();           

複制

如果确定

Optional

對象的值不為null,則可用

of()

方法。

//建立包裝對象值非空的Optional對象
Optional optional = Optional.of("Hello Java");

//傳入null,抛出NullPointerException
Optional<Object> o = Optional.of(null);           

複制

如果不确定

Optional

對象的值是否為null,則可用

ofNullable()

//建立包裝對象值允許為空也可以不為空的Optional對象
Optional optional = Optional.ofNullable("Hello Java");

通過調用其isPresent方法可以檢視該Optional中是否值為null。isPresent()方法就是會傳回一個boolean類型值,如果對象不為空則為真,如果為空則false 
boolean flag = optional.isPresent();
System.out.println(flag);           

複制

get

描述:傳回一個option的執行個體值。

Optional<String> op1 = Optional.of("Tom");
String s1 = op1.get();
System.out.println(s1);

備注:如果Optional為null,此時會抛出空指針           

複制

isPresent&ifPresent

描述:值存在傳回true,否則傳回false

Optional<String> optiona2 = Optional.of("Hello Java");
System.out.println(optiona2.isPresent());

Optional<String> op1 = Optional.of("Tom");
Optional<String> op2 = Optional.empty();

op1.ifPresent(s -> System.out.println("有值:" + s));
op1.ifPresent(System.out::println);           

複制

orElse

描述:如果有值就傳回,否則傳回一個給定的值作為預設值

Optional<String> op1 = Optional.of("Tom");
Optional<String> op2 = Optional.empty();

String s3 = op1.orElse("Bob");
String s4 = op2.orElse("Bob");
System.out.println(s3);
System.out.println(s4);

Tom
Bob           

複制

orElseGet

描述:orElseGet()方法與orElse()方法作用類似,但生成預設值的方式不同。該方法接受一個Supplier函數式接口參數,用于生成預設值。

Optional<String> op2 = Optional.empty();
String s5 = op2.orElseGet(() -> {
     return "Hello";
});
System.out.println(s5);           

複制

orElseThrow

描述:orElseThrow()方法與get()方法類似,當值為null時調用會抛出NullPointerException異常,但該方法可以指定抛出的異常類型。

Optional.empty().orElseThrow(() -> new RuntimeException("抛出異常了"));

Exception in thread "main" java.lang.RuntimeException: 抛出異常了           

複制

map

描述:将對應Funcation函數式接口中的對象,進行二次運算,封裝成新的對象然後傳回在Optional中。

Person person = new Person();
Optional optional = Optional.ofNullable(person);
System.out.println(optional.map(Person::getName));

Optional<String> optional = Optional.of("xiaoming");
String s = optional.map(e -> e.toUpperCase()).orElse("shiyilingfeng");
System.out.println(s); //輸出: XIAOMING           

複制

flatMap

描述:如果有值,為其執行mapping函數傳回Optional類型傳回值,否則傳回空Optional。與map不同的是,flatMap 的傳回值必須是Optional,而map的傳回值可以是任意的類型T。

Optional<String> optional = Optional.of("xiaoming");
Optional<String> s = optional.flatMap(e -> Optional.of(e.toUpperCase()));
System.out.println(s.get()); //輸出:XIAOMING           

複制

filter

描述:用于判斷Optional對象是否滿足給定條件,一般用于條件過濾。

List<String> strings = Arrays.asList("rmb", "doller", "ou");
for (String s : strings) {

  Optional<String> o = Optional.of(s).filter(s1 -> !s1.contains("o"));
  System.out.println(o.orElse("沒有不包含o的"));
}
//輸出:
rmb
沒有不包含o的
沒有不包含o的           

複制