原創(chuàng)性聲明:本文完全為筆者原創(chuàng),請尊重筆者勞動力。轉(zhuǎn)載務(wù)必注明原文地址。
2014年java8發(fā)布后,許多新特性被廣泛應(yīng)用。個人認(rèn)為,最高頻出現(xiàn)的就是以下三個新東西:
1.
Optional類
2.新的日期類Calendar
3.Lambda表達式
今天我先整理一下Optional類。它有以下幾個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
這個類的作用是什么呢?(下面針對幾個常用的舉例說明)
解決java開發(fā)人員避免空指針異常而做的繁瑣的if...else處理。
比如,有一個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è)上面不存在空指針問題,代碼可以精簡如下:
Article article = articleRepository.findOne(id);
if (article.getName().equal("java 8中的Optional")) {
return true;
} else {
return false;
}
但事實我們不得不去判斷空指針異常,因為數(shù)據(jù)庫中可能不存在id對應(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);
三行代碼,精簡、嚴(yán)謹(jǐn)、優(yōu)雅。
雖然可能初次接觸Optional可能會有點不容易理解。
上面的結(jié)構(gòu)其實可以這樣去理解:
return Optional.ofNullable(...) //1
.map(...) //2
.map(...) //3
.orElse(...); //4
下面詳細解釋一下:
括號1中代表初始數(shù)據(jù)(article),作為參數(shù)傳入OfNullable方法,這個方法其實是構(gòu)建一個Optional封裝類,把數(shù)據(jù)articleRepository.findOne(id)的返回值包裝進去,如果這個返回值是null,直接執(zhí)行orElse方法,也就是取false,相當(dāng)于直接return false,如果不是null,執(zhí)行第一個map方法,map方法的參數(shù)是一個Lambda表達式,c代表了Optional包裝的非空數(shù)據(jù)(即articleRepository.findOne(id)的返回值,已經(jīng)確保了非空),接著c.getName()將會被執(zhí)行,返回值將會繼續(xù)被封裝成Optional,如果這個返回值(name)為null,將會執(zhí)行orElse,結(jié)果仍為return false,如果非空,繼續(xù)下一個map方法,同理,第二個map方法也是一個Lambda表達式, 第一個map方法的返回值(Optional)所包裝的非空數(shù)據(jù)(name)將會被傳入第二個map方法的name參數(shù)中,然后繼續(xù)執(zhí)行name.equal("java 8中的Optional"),后面沒有map方法了,所以這個語句的結(jié)果將會被作為整個Optional操作的結(jié)果。
上面的解釋就是這樣一個Optional操作的詳細解釋,所以顯然,map方法可以無限多。雖然解釋看上去很復(fù)雜,但是習(xí)慣了這樣的思維后,其實也就那回事兒。
另外,map方法里是一個Lambda表達式,所以,它里面可以做更多的事情,比如,我們希望再獲取article對象后,更改一下author屬性,再持久化操作, 可以這樣去修改第一個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);
它并不影響整個name的判斷,也很好的處理了更新article對象時的空指針問題。
tip: 注意,當(dāng)
Lambda表達式是語句塊(有{}時),里面需要顯式的加上return, return的數(shù)據(jù)會被封裝成Optional,其包裝的數(shù)據(jù)會被作為參數(shù)傳遞至下一個map, 并執(zhí)行下一輪map。
常用的方法還有一個filter,過濾。仍以上面為例,我們希望只對有效的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也值得一提,例如一個article被封裝好成為了Optional,假設(shè)為articleOpt,可以用articleOpt.ifPresent判斷是否為null,用articleOpt.get將封裝的數(shù)據(jù)實體取出。
更多關(guān)于
Optional的內(nèi)容還是自己看看官方API吧。