Java中Optional使用注意事項
阿新 • • 發佈:2022-05-04
前言
之前遇到過使用Optional之後帶來的隱含bug,現在強調記錄一下不好的用法,防止錯用。
Optional不能序列化,不能作為類的欄位(field)
這點尤為重要,即類要純粹。如果是POJO就原始型別就可以了,如果是領域物件,則更不應該使用Optional作為field。
Optional不能作為方法引數
另一種不太適合使用Optional的情況是將該型別作為方法或者建構函式的引數,這將導致不必要的程式碼複雜化。
User user = new User("[email protected]", "1234", Optional.empty());
相反,使用方法過載(method overloading)來處理非強制性引數要方便得多。
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("[email protected]", "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)的創始人。