點選上方藍色字型,選擇“标星公衆号”
優質文章,第一時間送達
作者 | zjhred
來源 | http://8rr.co/hsLh
引言
在文章的開頭,先說下NPE問題,NPE問題就是,我們在開發中經常碰到的NullPointerException.假設我們有兩個類,他們的UML類圖如下圖所示
在這種情況下,有如下代碼 user.getAddress().getProvince();
這種寫法,在user為null時,是有可能報NullPointerException異常的。為了解決這個問題,于是采用下面的寫法
這種寫法是比較醜陋的,為了避免上述醜陋的寫法,讓醜陋的設計變得優雅。JAVA8提供了Optional類來優化這種寫法,接下來的正文部分進行詳細說明 API介紹 先介紹一下API,與其他文章不同的是,本文采取類比的方式來講,同時結合源碼。而不像其他文章一樣,一個個API羅列出來,讓人找不到重點。
Optional(T value),empty(),of(T value),ofNullable(T value)
這四個函數之間具有相關性,是以放在一組進行記憶。 先說明一下,Optional(T value),即構造函數,它是private權限的,不能由外部調用的。其餘三個函數是public權限,供我們所調用。那麼,Optional的本質,就是内部儲存了一個真實的值,在構造的時候,就直接判斷其值是否為空。好吧,這麼說還是比較抽象。直接上Optional(T value)構造函數的源碼,如下圖所示
那麼,of(T value)的源碼如下:
也就是說of(T value)函數内部調用了構造函數。根據構造函數的源碼我們可以得出兩個結論:
- 通過of(T value)函數所構造出的Optional對象,當Value值為空時,依然會報NullPointerException。
- 通過of(T value)函數所構造出的Optional對象,當Value值不為空時,能正常構造Optional對象。
除此之外呢,Optional類内部還維護一個value為null的對象,大概就是長下面這樣的
那麼,
empty()
的作用就是傳回EMPTY對象。 好了鋪墊了這麼多,可以說
ofNullable(T value)
的作用了,上源碼
好吧,大家應該都看得懂什麼意思了。相比較of(T value)的差別就是,當value值為null時, of(T value) 會報NullPointerException異常; ofNullable(T value) 不會throw Exception, ofNullable(T value) 直接傳回一個EMPTY對象。 那是不是意味着,我們在項目中隻用ofNullable函數而不用of函數呢? 不是的,一個東西存在那麼自然有存在的價值。當我們在運作過程中,不想隐藏NullPointerException。而是要立即報告,這種情況下就用Of函數。但是不得不承認,這樣的場景真的很少。部落客也僅在寫junit測試用例中用到過此函數。 2、
orElse(T other),orElseGet(Supplier extends T> other)和orElseThrow(Supplier extends X> exceptionSupplier)
這三個函數放一組進行記憶,都是在構造函數傳入的value值為null時,進行調用的。orElse和orElseGet的用法如下所示,相當于value值為null時,給予一個預設值:
這兩個函數的差別:當user值不為null時,orElse函數依然會執行createUser()方法,而orElseGet函數并不會執行createUser()方法,大家可自行測試。 至于orElseThrow,就是value值為null時,直接抛一個異常出去,用法如下所示
3、
map(Function super T, ? extends U> mapper)和flatMap(Function super T, Optional> mapper)
這兩個函數放在一組記憶,這兩個函數做的是轉換值的操作。 直接上源碼
這兩個函數,在函數體上沒什麼差別。唯一差別的就是入參,map函數所接受的入參類型為
Function super T, ? extends U>
Function super T, Optional>
在具體用法上,對于map而言: 如果User結構是下面這樣的
這時候取name的寫法如下所示
對于flatMap而言: 如果User結構是下面這樣的
這時候取name的寫法如下所示
4、isPresent()和ifPresent(Consumer super T> consumer) 這兩個函數放在一起記憶,
isPresent
即判斷value值是否為空,而
ifPresent
就是在value值不為空時,做一些操作。這兩個函數的源碼如下
需要額外說明的是,大家千萬不要把
給寫成
因為這樣寫,代碼結構依然醜陋。部落客會在後面給出正确寫法 至于
ifPresent(Consumer super T> consumer)
,用法也很簡單,如下所示
5、filter(Predicate super T> predicate) 不多說,直接上源碼
filter 方法接受一個
Predicate
來對
Optional
中包含的值進行過濾,如果包含的值滿足條件,那麼還是傳回這個 Optional;否則傳回
Optional.empty
。 用法如下
如上所示,如果user的name的長度是小于6的,則傳回。如果是大于6的,則傳回一個EMPTY對象。
實戰使用
例一 在函數方法中, 以前寫法
JAVA8寫法
例二 比如,在主程式中, 以前寫法
JAVA8寫法
例三 以前寫法
java8寫法
其他的例子,不一一列舉了。不過采用這種鍊式程式設計,雖然代碼優雅了。但是,邏輯性沒那麼明顯,可讀性有所降低,大家項目中看情況酌情使用。
往期推薦
看完這篇還不了解 Nginx,那我就哭了!
[email protected]預設線程池導緻OOM問題
7000字 Redis 超詳細總結筆記總 | 收藏必備!
對MySQL的鎖了解嗎
Spring 最常用的 7 大類注解
Kafka 事務之偏移量的送出對資料的影響
中國網際網路史就是一部流氓史!
如何幹掉惡心的 SQL 注入?
Linux 最常用指令
MyBatis 事務管了解析:颠覆你心中對事務的了解!
好文章,我 在看 ❤️