來源:Medium 本文將幫助您在使用 Java 程式碼時更好地理解Optional 的用途。 當我第一次開始使用 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,我們可以使用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()方法的值。
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:
-
作為方法參數。如果方法參數可以為null,那麼從純程式碼的角度來看,傳遞null仍然優於傳遞Optional。此外,您可以建立重載方法來抽像地處理缺少 null 方法參數的情況。
-
表示缺少的 Collection 物件。集合可以為空,因此空集合(如空集合或列表)必須用於表示沒有值的集合。
GO TO FULL VERSION