原創(chuàng)性聲明:本文完全為筆者原創(chuàng)司恳,請(qǐng)尊重筆者勞動(dòng)力绍傲。轉(zhuǎn)載務(wù)必注明原文地址。
2014年java8發(fā)布后猎塞,許多新特性被廣泛應(yīng)用杠纵。個(gè)人認(rèn)為,最高頻出現(xiàn)的就是以下三個(gè)新東西:
1.
Optional
類
2.新的日期類Calendar
3.Lambda表達(dá)式
今天我先整理一下Optional
類铝量。它有以下幾個(gè)APi方法:
1. empty
2. equal
3. filter
4. flatMap
5. get
6. hashCode
7. ifPresent
8. map
9. of
10. ofNullable
11. orElse
12. orElseGet
13. orElseThrow
14. toString
這個(gè)類的作用是什么呢银亲?(下面針對(duì)幾個(gè)常用的舉例說明)
解決java開發(fā)人員避免空指針異常而做的繁瑣的if...else
處理。
比如拍谐,有一個(gè)Article
類馏段,它具有屬性name
,我們要判斷name屬性是否等于"java 8中的Optional"
亡蓉,我們可以這樣做:
Article article = articleRepository.findOne(id);
if (article != null) {
if (article.getName() != null) {
if (article.getName().equal("java 8中的Optional")) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
這沒毛病喷舀,而且可以說代碼非常嚴(yán)謹(jǐn)元咙。只是很多if...else
看上去并不好受巫员,而且其實(shí)上面的代碼看上去有很多,而功能卻很簡(jiǎn)單简识,假設(shè)上面不存在空指針問題感猛,代碼可以精簡(jiǎn)如下:
Article article = articleRepository.findOne(id);
if (article.getName().equal("java 8中的Optional")) {
return true;
} else {
return false;
}
但事實(shí)我們不得不去判斷空指針異常陪白,因?yàn)閿?shù)據(jù)庫中可能不存在id
對(duì)應(yīng)的article
膳灶,即使存在,它的name
可能也是null
序厉。但是Optional
類允許我們這樣做:
return Optional.ofNullable(articleRepository.findOne(id)).map(c -> c.getName())
.map(name -> name.equal("java 8中的Optional"))
.orElse(false);
三行代碼毕箍,精簡(jiǎn)、嚴(yán)謹(jǐn)文捶、優(yōu)雅媒咳。
雖然可能初次接觸Optional
可能會(huì)有點(diǎn)不容易理解。
上面的結(jié)構(gòu)其實(shí)可以這樣去理解:
return Optional.ofNullable(...) //1
.map(...) //2
.map(...) //3
.orElse(...); //4
下面詳細(xì)解釋一下:
括號(hào)1中代表初始數(shù)據(jù)(article
)恨搓,作為參數(shù)傳入OfNullable
方法筏养,這個(gè)方法其實(shí)是構(gòu)建一個(gè)Optional
封裝類,把數(shù)據(jù)articleRepository.findOne(id)
的返回值包裝進(jìn)去辉浦,如果這個(gè)返回值是null
,直接執(zhí)行orElse
方法茎辐,也就是取false
,相當(dāng)于直接return false
弛槐,如果不是null
依啰,執(zhí)行第一個(gè)map
方法,map
方法的參數(shù)是一個(gè)Lambda
表達(dá)式叹誉,c
代表了Optional
包裝的非空數(shù)據(jù)(即articleRepository.findOne(id)
的返回值,已經(jīng)確保了非空),接著c.getName()
將會(huì)被執(zhí)行钧唐,返回值將會(huì)繼續(xù)被封裝成Optional
匠襟,如果這個(gè)返回值(name
)為null
,將會(huì)執(zhí)行orElse
,結(jié)果仍為return false
酸舍,如果非空父腕,繼續(xù)下一個(gè)map
方法,同理璧亮,第二個(gè)map
方法也是一個(gè)Lambda
表達(dá)式, 第一個(gè)map方法的返回值(Optional)所包裝的非空數(shù)據(jù)(name)將會(huì)被傳入第二個(gè)map
方法的name
參數(shù)中枝嘶,然后繼續(xù)執(zhí)行name.equal("java 8中的Optional")
,后面沒有map
方法了,所以這個(gè)語句的結(jié)果將會(huì)被作為整個(gè)Optional
操作的結(jié)果群扶。
上面的解釋就是這樣一個(gè)Optional
操作的詳細(xì)解釋竞阐,所以顯然,map
方法可以無限多骆莹。雖然解釋看上去很復(fù)雜幕垦,但是習(xí)慣了這樣的思維后,其實(shí)也就那回事兒先改。
另外仇奶,map方法里是一個(gè)Lambda
表達(dá)式,所以,它里面可以做更多的事情嫁艇,比如弦撩,我們希望再獲取article
對(duì)象后论皆,更改一下author
屬性点晴,再持久化操作, 可以這樣去修改第一個(gè)map
方法:
return Optional.ofNullable(articleRepository.findOne(id))
.map(c -> {
c.setAuthor("dongfangyihaolan");
articleRepository.saveAndFlush(c);
return c.getName()
})
.map(name -> name.equal("java 8中的Optional"))
.orElse(false);
它并不影響整個(gè)name
的判斷陪竿,也很好的處理了更新article
對(duì)象時(shí)的空指針問題屠橄。
tip: 注意,當(dāng)
Lambda
表達(dá)式是語句塊(有{}時(shí))礁哄,里面需要顯式的加上return
溪北, return的數(shù)據(jù)會(huì)被封裝成Optional
,其包裝的數(shù)據(jù)會(huì)被作為參數(shù)傳遞至下一個(gè)map
, 并執(zhí)行下一輪map
茉继。
常用的方法還有一個(gè)filter
蚀乔,過濾。仍以上面為例乙墙,我們希望只對(duì)有效的article
執(zhí)行后面的map操作,該如何听想?
你當(dāng)然可以在jpa方法上做過濾查詢或者在return c.getName()
前做是否有效判斷汉买,但是現(xiàn)在用filter
也可以做到。如下:
return Optional.ofNullable(articleRepository.findOne(id))
.filter(c -> ifEffect(c))
.map(c -> c.getName())
.map(name -> name.equal("java 8中的Optional"))
.orElse(false);
ifEffect()
是自定義判斷是否有效的方法。如果為false
,也將執(zhí)行orElse
垫卤,為true
才去繼續(xù)執(zhí)行map
。
同樣歇盼,filter也可以用語句塊的形式评抚,完成更多的處理。
還有ifPresent
和get
也值得一提邢笙,例如一個(gè)article
被封裝好成為了Optional
侍匙,假設(shè)為articleOpt
,可以用articleOpt.ifPresent
判斷是否為null妇汗,用articleOpt.get
將封裝的數(shù)據(jù)實(shí)體取出江滨。
更多關(guān)于
Optional
的內(nèi)容還是自己看看官方API吧。