首頁>科技>

Optional 類位於 java.util 包下,自 JDK 1.8 版本新增的,它是一個 final 類,不能被繼承,且構造函數是 private 的,不能被實例化,它提供了一系列對 null 空值的處理方法,是一個包裝類,既可以包裝非空對象,也可以包裝空值,下面來看看它的定義以及默認構造函數。

眾所周知,在Java開發過程中,經常需要對 null 進行判斷和處理,如果漏掉了,就會引發 NullPointerException 異常,因此 null 判斷幾乎會遍佈在代碼的每個角落,那麼神奇的 null 是如何誕生的呢?

1965年,英國一位名為Tony Hoare的計算機科學家在設計ALGOL W語言時提出了null引用的想法。ALGOL W是第一批在堆上分配記錄的類型語言之一。Hoare選擇null引用這種方式,“只是因為這種方法實現起來非常容易”。雖然他的設計初衷就是要“通過編譯器的自動檢測機制,確保所有使用引用的地方都是絕對安全的”,他還是決定為null引用開個綠燈,因為他認為這是為“不存在的值”建模最容易的方式。很多年後,他開始為自己曾經做過這樣的決定而後悔不迭,把它稱為“我價值百萬的重大失誤”。(引自網絡)

其實, null 引入的目的是為了表示變量值的缺失。那麼在Java 8 中為什麼會引入這樣的一個 Optional 類呢?主要是為了對存在或缺失的變量值建模,這樣一來,不管變量有沒有值,都可以統一使用 Optional 來表示,它可以減少 null 值的判斷邏輯,使得代碼結構更加簡單,同時也可以減少 NullPointerException 異常的出現。

1、構造函數

Optional 類提供了兩個構造函數,都是 private 的,如下:

因為構造函數是私有的,所以不能直接實例化 Optional 類,那麼如果創建 Optional 實例呢?可以通過以下的三個方法:

empty() :通過靜態工廠方法創建一個空的 Optional 實例;of() :將指定值用 Optional 封裝之後返回,如果該值為 null ,則拋出一個 NullPointerException 異常;ofNullable() :將指定值用 Optional 封裝之後返回,如果該值為 null ,則返回一個空的 Optional 對象;2、方法Optional 類提供了一些方法,主要分為 靜態方法和實例方法 ,像上面提到的三個方法,都是靜態方法,主要用於創建 Optional 實例。

2.1 靜態方法(1)empty()empty() 方法是通過靜態工廠方法創建一個空的 Optional 實例,不包含任何值,其定義如下:

如果直接調用 empty() 方法,將會直接返回靜態常量 EMPTY .

(2)of() of() 方法將指定值用 Optional 封裝之後返回,如果該值為 null ,則拋出一個 NullPointerException 異常,其源碼如下:

public static <T> Optional<T> of(T value) {        return new Optional<>(value); }

直接是通過 new Optional(T value) 方法創建實例,該構造方法使用 Objects.requireNonNull() 對傳入的參數進行檢查,其源碼如下:

public static <T> T requireNonNull(T obj) {        if (obj == null)               throw new NullPointerException();        return obj; }

也就是說 of() 方法不接受 null 空值。

(3)ofNullable() ofNullable() 方法將指定值用 Optional 封裝之後返回,如果該值為 null ,則返回一個空的 Optional 對象,其定義如下:

public static <T> Optional<T> ofNullable(T value) {         return value == null ? empty() : of(value); }

從實現可以看出, ofNullable() 方法可以接受 null 空值,而 of() 方法不能接收空值,這也是它與 of() 方法之間的區別。

2.2 實例方法 (1)get() get() 方法是用來獲取 Optional 封裝的值的,如果該值存在,將該值用 Optional 封裝返回,否則拋出一個 NoSuchElementException 異常,其定義如下:

public T get() {        if (value == null) {                throw new NoSuchElementException("No value present");   }        return value; }

其中的 value 值是 Optional 中的成員變量,其定義如下:

private final T value;

(2)isPresent() isPresent() 方法用於判斷 value 值是否存在,如果值存在就返回true,否則返回false,其定義如下:

public boolean isPresent() {         return value != null; }

(3)ifPresent() ifPresent() 方法也是用於判斷 value 值是否存在,如果值存在,就執行使用該值的方法調用,否則什麼也不做,其定義如下:

public void ifPresent(Consumer<? super T> consumer) {        if (value != null)               consumer.accept(value);    }

該方法的參數是 Consumer ,如果 value 值存在,則會傳入到 Consumer.accept() 方法中,其中 Consumer 類是一個功能性接口,其定義如下:

@FunctionalInterface public interface Consumer<T> {         void accept(T t);         default Consumer<T> andThen(Consumer<? super T> after) {             Objects.requireNonNull(after);                      return (T t) -> { accept(t); after.accept(t);     };         } }

(4)filter() filter() 方法主要用於條件過濾,如果值存在並且滿足提供的謂詞,就返回包含該值的 Optional 對象;否則返回一個空的 Optional 對象,其定義如下:

public Optional<T> filter(Predicate<? super T> predicate) {     // filter 方法中的謂詞參數不能為空,否則會拋出空指針異常          Objects.requireNonNull(predicate);          if (!isPresent())                  return this;          else                  return predicate.test(value) ? this : empty(); }

filter() 方法的參數是需要傳入一個 Predicate 謂詞,並且參數不能為 null ,否則會拋出 NullPointerException 異常,當 value 值存在時,會調用 Predicate.test() 方法進行判斷。

(5)map() map() 方法主要是對 Optional 封裝的值執行 mapping 函數,如果值存在,就對該值執行提供的mapping函數調用,如果值不存在,則直接返回空的 Optional 對象,其定義如下:

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {     // map 方法中的參數 mapper 函數不能為空,否則會拋出空指針異常     Objects.requireNonNull(mapper);     if (!isPresent())         return empty();     else {         return Optional.ofNullable(mapper.apply(value));     } } 複製代碼

(6)flatMap() flatMap() 方法主要也是對 Optional 封裝的值執行 mapping 函數,如果值存在,就對該值執行提供的mapping函數調用,返回一個 Optional 類型的值,否則就返回一個空的 Optional 對象,其定義如下:

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {     // flatMap 方法中的參數 mapper 函數不能為空,否則會拋出空指針異常     Objects.requireNonNull(mapper);     if (!isPresent())         return empty();     else {         return Objects.requireNonNull(mapper.apply(value));     } } 複製代碼

flatMap() 方法和 map() 方法有什麼區別呢?從方法定義的參數

(7)orElse() orElse() 方法主要用於如果有值,直接返回,如果沒有值時,則返回該方法設置的默認值,其源碼如下:

public T orElse(T other) {     return value != null ? value : other; } 複製代碼

(8)orElseGet() orElseGet() 方法和 orElse() 方法的作用類似,只是當沒有值時, orElseGet() 方法不是直接返回一個值,而是一個由指定的 Supplier 接口返回的值,其定義如下:

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

(9)orElseThrow() orElseThrow() 方法用於如果有值,則直接返回,如果沒有值,則直接拋出一個由指定的 Supplier 接口生成的異常,其定義如下:

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {     // 如果值不為 null,直接返回     if (value != null) {         return value;     } else {         throw exceptionSupplier.get();     } } 複製代碼

3、其他相關類 除了 Optional 類外, java.util 包下還提供了另外的三個基礎類型的 Optional 類,如下:

OptionalInt OptionalLong OptionalDouble 複製代碼

這三個類的源碼與 Optional 類似,只是 Optional 類使用了泛型定義,而它們只能應用於基礎數據類型。

4
最新評論
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 買房的時候,只剩下一樓和頂樓了,怎麼選?