Optional 理解
1. 含義
Optional 是一個容器對象,該容器里可能包含非空值也可能不包含非空值。最主要的用途就是為了規避 NPE 異常(傳入的對象為 null 造成)。
- 如果存在值,通過
isPresent方法返回 true,通過get方法獲取 value
Optional 也提供了額外的方法,這些方法根據是否存在 value 來發揮作用。
注意
請不要在 Optional 對象中使用 hashcode,synchronized ,== ,否則會產生不可預料的影響。因為 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方法返回值,否則返回空Optionalpublic<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 時,應該使用函數式的編程風格。
