JavaRush /Java Blog /Random-TW /喝咖啡休息#161。如何使用Optional在Java中處理Null

喝咖啡休息#161。如何使用Optional在Java中處理Null

在 Random-TW 群組發布
來源:Medium 本文將幫助您在使用 Java 程式碼時更好地理解Optional 的用途。 喝咖啡休息#161。 如何使用Optional在Java中處理Null - 1當我第一次開始使用 Java 程式碼時,常常有人建議我使用Optional。但當時我不太明白為什麼使用Optional比實現空值處理好。在這篇文章中,我想與大家分享為什麼我認為我們都應該更多地使用Optional,以及如何避免過度可選化你的程式碼,這對程式碼品質是不利的。

什麼是可選的?

Optional 參數用於攜帶物件並使空引用能夠由各種 API 處理。我們來看一下程式碼片段:
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
我們有一個Coffee實例,其中我們從Sugar物件的實例中取得一些糖。如果我們假設從未在Coffee建構函式中設定數量值,則Coffee.getSugar().getQuantity()將傳回NullPointerException。當然,我們總是可以使用舊的檢查來解決問題。
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
現在一切似乎都很好。但在編寫Java程式碼時,我們最好避免實作檢查。讓我們看看如何使用Optional 來完成此操作。

如何建立可選

創建Optional物件的方法有3種:
  • of(T value) — 可選非空物件的實例化。請注意,使用of()引用null物件將引發NullPointerException

  • ofNullable(T value) - 為可以為 null 的物件建立一個可選值。

  • empty() - 建立一個表示對null 的參考的選用實例。

// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
所以你有一個可選對象。現在我們來看看Optional的兩個主要方法:
  • isPresent() - 此方法告訴您Optional 物件是否包含非空值。

  • get() - 使用目前值檢索可選值。請注意,對空的Optional呼叫get()將導致NullPointerException

請注意,如果您在使用Optional時只使用get()isPresent() ,那麼您就錯過了!為了理解這一點,現在讓我們用Optional來重寫上面的範例。

使用可選改進空檢查

那我們要如何改進上面的程式碼呢?透過Optional,我們可以使用isPresent()來了解物件的存在,並使用get()檢索它。我們首先將coffee.getSugar()的結果與Optional 一起打包並使用isPresent()方法。這將幫助我們確定getSugar()是否回傳null。
Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
  Sugar sugar = sugar.get();
  int quantity = sugar.getQuantity();
}
看這個例子,將coffee.getSugar() 的結果打包到Optional中似乎並沒有增加任何價值,反而增加了麻煩。我們可以透過使用我認為是可選類別中我最喜歡的函數來改進結果:
  • map(Function<? super T,? extends U> mapper) - 將Optional中包含的值對應到提供的函數。如果Optional參數為空,則map()將傳回Optional.empty()

  • orElse(T other)是get()方法的「特殊」版本。它可以取得Optional中包含的值。但是,如果是空Optional,這將傳回傳遞給orElse()方法的值。

此方法將傳回Optional實例中包含的值。但如果Optional參數為空,表示它不包含任何值,那麼orElse()將傳回傳遞給其方法簽署的值,該值稱為預設值。
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
這真的很酷——至少我這麼認為。現在,如果在空值的情況下我們不想返回預設值,那麼我們需要拋出某種異常。 orElseThrow(Supplier<? extends X> exceptionSupplier)傳回Optional參數中包含的值,或如果Optional為空則拋出異常。
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
正如您所看到的,Optional 提供了幾個優點:
  • 摘要空檢查
  • 提供用於處理null物件的 API
  • 允許使用聲明性方法來表達正在實現的目標

如何透過可選方式變得有效

在我的工作中,當方法可以傳回「無結果」狀態時,我使用Optional作為傳回類型。我通常在定義方法的返回類型時使用它。
Optional<Coffee> findByName(String name) {
   ...
}
有時這是沒有必要的。例如,如果我有一個傳回int 的方法,例如Sugar類別中的getQuantity(),那麼如果結果為null表示“無數量”,則該方法可能會傳回0 。現在,知道了這一點,我們可以認為Coffee類別中的Sugar參數可以表示為Optional。乍一看,這似乎是個好主意,因為從理論上講,咖啡中不需要含有糖。然而,這就是我想解決什麼時候不使用Optional的地方。 在以下場景中我們應該避免使用Optional:
  • 作為POJO(例如DTO)的參數類型。可選值不可序列化,因此在 POJO 中使用它們會使物件不可序列化。

  • 作為方法參數。如果方法參數可以為null,那麼從純程式碼的角度來看,傳遞null仍然優於傳遞Optional。此外,您可以建立重載方法來抽像地處理缺少 null 方法參數的情況。

  • 表示缺少的 Collection 物件。集合可以為空,因此空集合如空集合列表必須用於表示沒有值的集合。

結論

Optional 已成為 Java 函式庫的強大補充。它提供了一種處理可能不存在的物件的方法。因此,在製定方法時應予以考慮,不要陷入濫用的陷阱。是的,您可以編寫出色的程式碼來實作 null 檢查和 null 處理,但 Java 社群更喜歡使用Optional。它有效地傳達瞭如何處理缺失值,比混亂的 Null 檢查更容易閱讀,並且從長遠來看可以減少程式碼中的錯誤。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION