Optional 理解


Optional 理解

1. 含義

Optional 是一個容器對象,該容器里可能包含非空值也可能不包含非空值。最主要的用途就是為了規避 NPE 異常(傳入的對象為 null 造成)。

  • 如果存在值,通過 isPresent 方法返回 true,通過 get 方法獲取 value

Optional 也提供了額外的方法,這些方法根據是否存在 value 來發揮作用。

注意

請不要在 Optional 對象中使用 hashcodesynchronized== ,否則會產生不可預料的影響。因為 Optional 是基於值的類。

基於值的類(Value-based Classes)

關於什么是 Value-based Clases,我找到 Oracle 的一篇官方文檔:Value-based Classes

某些類(如 java.util.Optional 和 java.time.LocalDateTime) 是基於值的。基於值的實例有如下特征:

  • 具有 final 屬性,是不可更改的(盡管可能包含對可變對象的引用)
  • 具有 equals()hashCode()toString() 方法的實現,且實現方法僅依賴於實例自身的狀態發生變化,而不依賴外部的對象或變量的狀態
  • 不使用身份敏感的操作,使用 == 比較兩個實例,使用 hashcode 獲取實例信息,使用 synchronized 獲取內部鎖
  • 兩實例是否相同是根據 equals() 方法而不是 ==
  • 沒有公開的構造方法,而是通過工廠方法(Factory method)來產生實例
  • 若兩實例相同,則可以互相替代,且不會有不同的行為

2. Optional 類中方法

2.1 構造方法
private Optional(T value) {
    this.value = Objects.requireNonNull(value);
}
  • Optional 是一個容器,容器里面包着一個值,這個值是泛型

  • 因為構造方法私有化,所以不能通過 new 新建 Optional 對象,只能通過靜態工廠方法構造對象

2.2 創建 Optional 對象方法
  • of:返回一個容器的值不為 null 的對象,使用該方法要求調用者調用 of 方法時,參數值不為空,否則會拋出 NPE 異常。

    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
    
  • ofNullable:構造一個可能為空,也可能不為空的 optional 對象。

    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
    
  • empty:返回容器的值為 null 的對象

    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
    
2.3 其他方法
  • isPresent:判斷該對象是否存在

  • get:獲取容器的值

  • orElse:容器值不為空,將 value 打印出來;為空,返回指定值。

    public T orElse(T other) {
        return value != null ? value : other;
    }
    
  • orElseGet:該方法不接受參數。容器值不為空,返回 value;為空,返回指定值

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }
    

    舉例:

    System.out.println(optional.orElseGet(() -> "nihao"));
    
  • orElseThrow:容器值不為空,返回 value;為空,拋出異常。

  • map:映射,將一個值映射成另一個值。如果有值,則對其執行調用映射函數得到返回值。如果返回值不為 null ,則創建包含映射返回值的 Optional 作為 map 方法返回值,否則返回空 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));
        }
    }
    

    舉例:

    System.out.println(optional.map(thecompant -> theCompany.getEmployees()).
                       orElse(Collections.emptylist()));
    

注意
在企業開發中,我們經常通過 orElse 來規避 NPE 異常。

3. Optional 對象不應該作為方法參數

Optional 無法被序列化。所以不要試圖將 Optional 作為方法參數進行定義,也不要在類當中聲明 Optional 類型的成員變量。Optional 通常只作為方法的返回值,用來規避空指針異常。

在使用 Optional 時,應該使用函數式的編程風格。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM