為什麼要使用 Java Optional 以及 Optional 常用的方法有哪些

你用過 Java Optional 嗎?

本文假設讀者你已經用過 Optional 或是介接過回傳 Optional 的 API,知道 Optional 主要是解決 java.lang.NullPointerException(剛好是本站用的網址 XD),但還是不太知道為什麼要用 Optional!

換個角度看 Java Optional

我覺得站在開發 API 的角度來看這個問題,就很清楚為何要使用 Optional!

  • 如果回傳的結果可能為 null 就該用 Optional<T>。
  • 反之,不可能回傳 null 就跟以前一樣就用 T。

使用你 API 的人,就可以根據這個資訊,知道呼叫這個方法需不需要處理 null 的問題,而不是每個方法都要多寫處理 null 的邏輯,或是沒處裡就會發生 java.lang.NullPointerException。

// 回傳 People 代表這方法絕對會回傳一個我爸
public People getMyFather()

// 回傳 <Optional>People 代表可能回傳空物件
public <Optional>People getMyFather()

如果今天你寫的系統,每個人都必定會有個爸爸,那回傳 People 的 getMyFather() 符合你的意圖,而回傳 <Optional>People 的 getMyFather() 因為有可能回傳空物件的語意,所以就不適合用此方法。

若你寫的系統允許父不詳的狀況,那回傳 <Optional>People 的 getMyFather() 就是比較好的寫法。

我看到第一個回傳 People 的 getMyFather(),我很清楚我不用處理 null 的狀況,也就不用多寫處理 null 的邏輯。而第二個方法我就需要用 isPresent() 檢查回傳的 Optional<People>是否為一個空物件。

Java Optional 常用的方法整理

下面程式碼說明 of、ofNullable 這兩個方法:

Foo foo = null;

// of()不接受傳入 null,此處會發生 NullPointerException
Optional<Foo> optionalFoo1 = Optional.of(foo);

// ofNullable()可以傳入 null,此處會得到一個空物件 
Optional<Foo> optionalFoo2 = Optional.ofNullable(foo);

下面程式碼說明 ifPresent、get、getElse、orElseGet、orElseThrow:

// 從 getBar 取得一個 Optional<Bar>
// 由回傳 Optional<Bar> 來看
// 我們預期有可能收到空物件
Optional<Bar> optionalBar = getBar();

// 用 ifPresent + get 的寫法跟原本檢查 null 的寫法一樣差
if (optionalBar.ifPresent()) // 檢查是否為空物件
{
  Bar bar = optionalBar.get(); // 取得包在裏頭的 bar
  bar.doSometing();
}

// 當 optionalBar 裏頭包的是 null,會建立一個新的 Bar 物件並回傳
Bar bar = optionalBar.getElse(new Bar());

// 當 optionalBar 裏頭包的是 null,會建立一個新的 Bar 物件並回傳
Bar bar = optionalBar.orElseGet(() -> { 
    // 這邊可以多做一些事,比如印 Log
    return new Bar();
}));

// 當 optionalBar 裏頭包的是 null,會丟出一個自訂的例外
Bar bar = optionalBar.orElseThrow(() -> new MyException("WTF")));

結語

開發 API 的人使用 Optional 來說明回傳的物件是不是有可能為 null,讓使用 API 的人看到介面就知道是否要處理 null。

而 getElse() 能改善以往檢查是否為空,如果不為空就...的寫法,讓程式碼更簡潔更容易閱讀。

1 則回應:

atsome 提到...

看到有Optional就知道可能會回傳null
然後一定要寫處理null的事件

但如果看到T
也不能保証沒有null