java.lang.NullPointerException,只要敢自稱Java程序員,那對這個異常就再熟悉不過了。爲了防止拋出這個異常,咱們常常會寫出這樣的代碼:
Person person = people.find("John Smith");
if (person != null) {
person.doSomething();
}java
遺憾的是,在絕大多數Java代碼裏,咱們經常忘記了判斷空引用,因此,NullPointerException便也隨之而來了。
「Null Sucks.」,這就是Doug Lea對空的評價。做爲一個Java程序員,若是你還不知道Doug Lea是誰,那趕忙補課,沒有他的貢獻,咱們還只能用着Java最原始的裝備處理多線程。
"I call it my billion-dollar mistake.",有資格說這話是空引用的發明者,Sir C. A. R. Hoare。你能夠不知道Doug Lea,但你必定要知道這位老人家,不然,你便沒資格使用快速排序。程序員
在Java世界裏,解決空引用問題常見的一種辦法是,使用Null Object模式。這樣的話,在「沒有什麼」的狀況下,就返回Null Object,客戶端代碼就不用判斷是否爲空了。可是,這種作法也有一些問題。首先,咱們確定要爲Null Object編寫代碼,並且,若是咱們想大規模應用這個模式,咱們要爲幾乎每一個類編寫Null Object。
幸虧,咱們還有另一種選擇:Optional。Optional是對能夠爲空的對象進行的封裝,它實現起來並不複雜。在某些語言裏,好比Scala,Optional實現成了語言的一部分。而對於Java程序員而言,Guava爲咱們提供了Optional的支持。閒言少敘,先來如何使用Optional,完成前面的那段代碼。
Optional person = people.find("John Smith");
if (person.isPresent()) {
person.get().doSomething();
}多線程
這裏若是isPresent()返回false,說明這是個空對象,不然,咱們就能夠把其中的內容取出來作本身想作的操做了。
若是你期待的是代碼量的減小,恐怕這裏要讓你失望了。單從代碼量上來講,Optional甚至比原來的代碼還多。但好處在於,你絕對不會忘記判空,由於這裏咱們獲得的不是Person類的對象,而是Optional。
看完了客戶端代碼,咱們再來看看怎樣建立一個Optional對象,基本的規則很簡單:
若是咱們知道本身要封裝的對象是一個空對象,能夠用 Optional.absent();
若是封裝的對象是一個非空對象,則能夠用 Optional.of(obj);
若是不知道對象是否爲空,就這樣建立建立 Optional.fromNullable(obj);spa
有時候,當一個對象爲null的時候,咱們並非簡單的忽略,而是給出一個缺省值,好比找不到這我的,任務就交給經理來作。使用Optional能夠很容易地作到這一點,以上面的代碼爲例:
Optional person = people.find("John Smith");
person.or(manager).doSomething()
說白了,Optinal是給了咱們一個更有意義的「空」。線程