1. 程式人生 > 其它 >java8 Optional

java8 Optional

這篇文章主要結合原始碼去理解學習Optional類,本人能力有限,或許有些地方不能理解,希望能有大佬解惑

java8 引入了一個比較有趣的特性--Optional類,ta主要用來解決空指標異常的問題

1.建立Optional

public final class Optional<T> {
   private static final Optional<?> EMPTY = new Optional<>();
  private final T value;
  private Optional() {
        this.value = null
; }   private Optional(T value) { this.value = Objects.requireNonNull(value); }

由於Optional類中構造方法都是private許可權的 所以只能根據下列方法獲取Optional例項

    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        
return t; } 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); }

empty() 建立一個value為null的的例項,(@SuppressWarnings("unchecked") 為忽略警告,在這裡我們不要管他)

of(T value) 內部呼叫了建構函式,通過檢視建構函式,發現呼叫了Objects.requireNonNull(value),檢查是否為空,如果為空丟擲NullPointerException,所以我們可以得出結論: of() 只能建立非空值,當確定value不為null時,我們才能通過 Optional.of(value) 來得到包含value的Optional例項

ofNullable(T value) 通過方法內部程式碼可以看出和of(T value)的區別只是當value為 null 時,ofNullable返回EMPTY物件

由此可以看出,在開發中用到ofNullable的機會比of大很多

程式碼:

        Optional<Object> empty = Optional.empty();
        Optional<String> _nonNull = Optional.of("_NonNull");
        Optional<Object> _null = Optional.ofNullable(null);

補充:Optional其實就是一個包裝類,可以裝空值和非空值,可以解決很多場景下的空指標異常

2.訪問Optional

   @NotNull @Contract(pure=true)public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
    public boolean isPresent() {
        return value != null;
    }
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }
    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);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
    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));
        }
    }
    public T orElse(T other) {
        return value != null ? value : other;
    }
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

@NotNull @Contract(pure=true) 為什麼會出現在這裡?

程式碼都很簡單

get() 獲取值,空值拋異常

isPresent() 判斷值是否存在

ifPresent(Consumer<? super T> consumer)傳入一個消費者,如果值存在就執行lambda表示式

filter(Predicate<? super T> predicate) 傳入謂詞進行過濾,如果value滿足條件則返回,不滿足返回EMPTY

map(Function<? super T, ? extends U> mapper),flatMap(Function<? super T, Optional<U>> mapper) 兩個方法都是對Optional中的值進行一系列操作,通過實現Function的lambda表示式傳入操作,通過原始碼可以看出,二者都要求Optional的值非空才能執行mapping函式,二者都返回Optional物件,但map會自動將結果封裝為Optional物件,flatMap則需要手動封裝到Optional

orElse(T other),orElseGet(Supplier<? extends T> other) 設定預設值,當value為空時,orElse返回引數值,orElseGet返回Supplier介面的執行結果,當value有值時,二者都返回value,區別在於orElse的預設值為引數,即在呼叫orElse時預設值已經存在,而orElseGet預設值是介面實現生成,引數為生成預設值的手段,即當呼叫orElseGet時,預設值還沒有生成,只提供了生成預設值的方法,在value為空時才生成預設值。

orElseThrow(Supplier<? extends X> exceptionSupplier) 當value為空時,丟擲異常,自己決定丟擲異常型別,而不是總丟擲NullPointerException


_nonNull.ifPresent(System.out::println);
Optional<Boolean> aBoolean = _nonNull.map(non -> non.contains("o"));
Optional<Boolean> aBoolean1 = aBoolean.filter(Boolean::booleanValue);