Java中Optional使用注意事項


i18n

前言

之前遇到過使用Optional之后帶來的隱含bug,現在強調記錄一下不好的用法,防止錯用。

Optional不能序列化,不能作為類的字段(field)

這點尤為重要,即類要純粹。如果是POJO就原始類型就可以了,如果是領域對象,則更不應該使用Optional作為field。

Optional不適合作為方法參數

另一種不太適合使用Optional的情況是將該類型作為方法或者構造函數的參數,這將導致不必要的代碼復雜化。

User user = new User("john@gmail.com", "1234", Optional.empty());

而且,內部如果忘記isPresent,會得到NoSuchElementException。所以

相反,使用方法重載(method overloading)來處理非強制性參數要方便得多。

推薦Optional作為函數返回值

使用Optional作為返回值可以增強stream處理,構建流式API. 比如, findFirst()就是返回一個Optional對象。

@Test
public void whenEmptyStream_thenReturnDefaultOptional() {
    List<User> users = new ArrayList<>();
    User user = users.stream().findFirst().orElse(new User("default", "1234"));
    
    assertEquals(user.getEmail(), "default");
}

Optional和steam組合更有益處

級聯調用是危險的,很容易產生空指針。比如

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();

在傳統做法里,

if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            if (isocode != null) {
                isocode = isocode.toUpperCase();
            }
        }
    }
}

使用Optional可以精簡代碼,降低復雜度:

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

總結

Optional類對我們最有幫助的一個用例是同Stream或者其他方法組合使用,這些方法會返回一個可構建流暢API的Optional值。如果僅僅作為判空,那么不要使用Optional,直接判null就好。

比如,使用Stream 的Optional對象的例子:

@Test
public void whenGetStream_thenOk() {
    User user = new User("john@gmail.com", "1234");
    List<String> emails = Optional.ofNullable(user)
      .stream()
      .filter(u -> u.getEmail() != null && u.getEmail().contains("@"))
      .map( u -> u.getEmail())
      .collect(Collectors.toList());
   
    assertTrue(emails.size() == 1);
    assertEquals(emails.get(0), user.getEmail());
}

參考

原文鏈接:https://stackify.com/optional-java/

關於作者:

Eugen是一名軟件工程師,對Spring、REST API、安全和教育擁有極大熱情。同時,他還是Baeldung(推特賬號@baeldung)的創始人。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM