您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)Java中Optional如何使用,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
Optional
很簡單的一個(gè)類,點(diǎn)開它的源代碼,其中所有的方法都是與null
相關(guān)聯(lián)的。
這是一個(gè)簡化我們處理null
的類。
它就是一個(gè)容器,其中有我們想要的對(duì)象,但是該對(duì)象有時(shí)候會(huì)是空,所以我們需要使用Optional
封裝好的方法來獲取需要的對(duì)象。從而很好地避免了空指針異常。
錯(cuò)誤示范
我看到網(wǎng)上很多人這么寫:
catRepository.findById(id).get();
下面是Spring Boot 1.5
的寫法,那請(qǐng)問:如果上面的寫法是正確的,那為什么還要大費(fèi)周章設(shè)計(jì)一個(gè)Optional
呢?
catRepository.findOne(id);
分析
通過get
是能獲取到我們需要的對(duì)象。
但是看看get
的源代碼,這樣寫,拋出了NoSuchElementException
異常,這個(gè)異常我們沒法在全局中處理它。
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; }
為什么不能再全局中處理呢?大家可以思考一下:
因?yàn)?code>NoSuchElementException覆蓋的范圍太廣了,只要是Optional
中有null
就會(huì)拋出NoSuchElementException
,很多情況下都會(huì)造成這種異常,那我們究竟要給用戶一個(gè)什么樣的提示信息好呢?最后還是給出500
服務(wù)器異常,那異常處理的意義何在呢?
所以我們需要用Optional
來拋出一個(gè)有特定范圍的能被全局準(zhǔn)確處理的異常。
Cat cat = catRepository.findOne(id); if (null == cat) { throw new EntityNotFoundException("該實(shí)體找不到"); } return cat;
思想都是一樣,我們不過是用一種更簡潔的寫法實(shí)現(xiàn)上面的功能。
實(shí)現(xiàn)
沒錯(cuò),就像下面一樣,我們只需要一行代碼!
public Cat findById(Long id) { return catRepository.findById(id).orElseThrow(EntityNotFoundException::new); }
findById
返回一個(gè)Optional
,然后調(diào)用該對(duì)象的orElseThrow
方法。
orElseThrow
方法,如果存在,返回包含的值,否則拋出異常。
該方法的參數(shù)是一個(gè)lamda
表達(dá)式。這里就不深究lamda
表達(dá)式的幾種類型了,如果感興趣可以自行研究下Function
、Consumer
、Predicate
、Supplier
這四個(gè)函數(shù)式接口的區(qū)別。
所以傳一個(gè)lamda
表達(dá)式進(jìn)去,然后IDEA
會(huì)給出警告:
Can be replaced with method reference
該lamda
表達(dá)式能被一個(gè)方法引用代替,Alt + Enter
,我們最終的代碼就長這樣:
這里的::
是lamda
表達(dá)式的一種簡寫,是Java8
中的新特性,看著可能有點(diǎn)奇怪,原來,編譯器比程序員聰明多了。
異常處理
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity<String> entityNotFoundHandler() { return new ResponseEntity<>("您要找的實(shí)體不存在", HttpStatus.NOT_FOUND); } }
寫個(gè)控制器增強(qiáng),全局處理異常,這里的RestControllerAdvice
又是一個(gè)組合注解:
處理異常,同時(shí)以Json
的格式返回。
@Test public void findById() throws Exception { this.mockMvc.perform(get("/cat/1")) .andDo(print()); }
寫個(gè)控制器的單元測試,查詢一個(gè)不存在的實(shí)體,運(yùn)行,看控制臺(tái)的打印輸出:
一勞永逸
一勞永逸,這是我們最喜歡的東西了。
return catRepository.findById(id).orElseThrow(EntityNotFoundException::new);
以后再查詢,就這一行,再也不用去判斷null
了。
NotNull
正所謂條條大路通羅馬,對(duì)null
的一勞永逸,我們這樣實(shí)現(xiàn),別人也可以那樣實(shí)現(xiàn)。
如果你在Spring
的項(xiàng)目中打過斷點(diǎn)調(diào)試的話,那我斷定你一定見過下面這行代碼:
Assert.notNull();
以下是該方法的源碼,注意這里的Assert
是org.springframework.util
包下的:
剛方法用于判斷null
,如果為空,則拋出異常。
隨便點(diǎn)開一個(gè)方法,都會(huì)在第一行為不該為null
的參數(shù)進(jìn)行判斷。
這里,不禁對(duì)整個(gè)框架肅然起敬,同樣一個(gè)方法,大牛寫了二十分鐘,而你寫了十分鐘,但是你卻去改了半個(gè)小時(shí)的bug
。
@Nullable
可能在上面看到了我們不熟悉的注解@Nullable
,表示從來沒見過,這個(gè)注解干什么用的呢?
萬能的StackOverflow
又給出了完美的回答:
這會(huì)讓你的代碼更清晰,如果你重寫這個(gè)方法,你也需要讓參數(shù)可為空。通常也用于代碼提示。
@Nullable
和@NotNull
這一對(duì)注解,沒什么實(shí)際意義,只是用于代碼更清晰,同時(shí)編譯器能給出我們提示。
總結(jié)
之前一直抱怨Java
更新的太快,學(xué)校教的是Java5
之前的東西,從Java5
開始有的注解,但是從來沒講過這個(gè)東西,然而去看看官方的描述:
其實(shí),Java
的每次更新,都是為了我們更簡潔優(yōu)雅的代碼而努力。去看看官方的描述,Java
讓我們將更多的精力放在think
上,而不是code
上。
上述就是小編為大家分享的Java中Optional如何使用了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。