<div class="copyright-area">原文出處: <a ref="nofollow" target="_blank" href="https://blog.kaaass.net/archives/764">kaaass</a></div>
Optional是Java8提供的為了解決null安全問題的一個API。善用Optional可以使我們代碼中很多繁瑣、丑陋的設計變得十分優雅。這篇文章是建立在你對Optional的用法有一定了解的基礎上的,如果你還不太了解Optional,可以先去看看相關教程,或者查閱Java文檔。
使用Optional,我們就可以把下面這樣的代碼進行改寫。
1
2
3
4
5
|
public
static
String getName(User u) {
if
(u ==
null
)
return
"Unknown"
;
return
u.name;
}
|
不過,千萬不要改寫成這副樣子。
1
2
3
4
5
6
|
public
static
String getName(User u) {
Optional<User> user = Optional.ofNullable(u);
if
(!user.isPresent())
return
"Unknown"
;
return
user.get().name;
}
|
這樣改寫非但不簡潔,而且其操作還是和第一段代碼一樣。無非就是用isPresent方法來替代u==null。這樣的改寫並不是Optional正確的用法,我們再來改寫一次。
1
2
3
4
5
|
public
static
String getName(User u) {
return
Optional.ofNullable(u)
.map(user->user.name)
.orElse(
"Unknown"
);
}
|
這樣才是正確使用Optional的姿勢。那么按照這種思路,我們可以安心的進行鏈式調用,而不是一層層判斷了。看一段代碼:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
static
String getChampionName(Competition comp)
throws
IllegalArgumentException {
if
(comp !=
null
) {
CompResult result = comp.getResult();
if
(result !=
null
) {
User champion = result.getChampion();
if
(champion !=
null
) {
return
champion.getName();
}
}
}
throw
new
IllegalArgumentException(
"The value of param comp isn't available."
);
}
|
由於種種原因(比如:比賽還沒有產生冠軍、方法的非正常調用、某個方法的實現里埋藏的大禮包等等),我們並不能開心的一路comp.getResult().getChampion().getName()到底。而其他語言比如kotlin,就提供了在語法層面的操作符加持:comp?.getResult()?.getChampion()?.getName()。所以講道理在Java里我們怎么辦!
讓我們看看經過Optional加持過后,這些代碼會變成什么樣子。
1
2
3
4
5
6
7
|
public
static
String getChampionName(Competition comp)
throws
IllegalArgumentException {
return
Optional.ofNullable(comp)
.map(c->c.getResult())
.map(r->r.getChampion())
.map(u->u.getName())
.orElseThrow(()->
new
IllegalArgumentException(
"The value of param comp isn't available."
));
}
|
這就很舒服了。Optional給了我們一個真正優雅的Java風格的方法來解決null安全問題。雖然沒有直接提供一個操作符寫起來短,但是代碼看起來依然很爽很舒服。更何況?.這樣的語法好不好看還見仁見智呢。
還有很多不錯的使用姿勢,比如為空則不打印可以這么寫:
1
|
string.ifPresent(System.out::println);
|
Optional的魅力還不止於此,Optional還有一些神奇的用法,比如Optional可以用來檢驗參數的合法性。
1
2
3
4
|
public
void
setName(String name)
throws
IllegalArgumentException {
this
.name = Optional.ofNullable(name).filter(User::isNameValid)
.orElseThrow(()->
new
IllegalArgumentException(
"Invalid username."
));
}
|
這樣寫參數合法性檢測,應該足夠優雅了吧。
參考資料
- 使用 Java8 Optional 的正確姿勢 – 隔葉黃鶯 Unmi Blog (https://unmi.cc/proper-ways-of-using-java8-optional/)
<!-- BEGIN #author-bio -->
</div>