在大熱的Spring Boot 2.0
中,在將原來的泛型改成了Optional
,旨在讓咱們的代碼更簡潔。java
很簡單的一個類,點開它的源代碼,其中全部的方法都是與null
相關聯的。程序員
這是一個簡化咱們處理null
的類。spring
它就是一個容器,其中有咱們想要的對象,可是該對象有時候會是空,因此咱們須要使用Optional
封裝好的方法來獲取須要的對象。從而很好地避免了空指針異常。服務器
我看到網上不少人這麼寫:框架
catRepository.findById(id).get();
下面是Spring Boot 1.5
的寫法,那請問:若是上面的寫法是正確的,那爲何還要大費周章設計一個Optional
呢?函數
catRepository.findOne(id);
經過get
是能獲取到咱們須要的對象。單元測試
可是看看get
的源代碼,這樣寫,拋出了NoSuchElementException
異常,這個異常咱們無法在全局中處理它。測試
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; }
爲何不能再全局中處理呢?你們能夠思考一下:this
由於NoSuchElementException
覆蓋的範圍太廣了,只要是Optional
中有null
就會拋出NoSuchElementException
,不少狀況下都會形成這種異常,那咱們究竟要給用戶一個什麼樣的提示信息好呢?最後仍是給出500
服務器異常,那異常處理的意義何在呢?spa
因此咱們須要用Optional
來拋出一個有特定範圍的能被全局準確處理的異常。
Cat cat = catRepository.findOne(id); if (null == cat) { throw new EntityNotFoundException("該實體找不到"); } return cat;
思想都是同樣,咱們不過是用一種更簡潔的寫法實現上面的功能。
沒錯,就像下面同樣,咱們只須要一行代碼!
public Cat findById(Long id) { return catRepository.findById(id).orElseThrow(EntityNotFoundException::new); }
findById
返回一個Optional
,而後調用該對象的orElseThrow
方法。
orElseThrow
方法,若是存在,返回包含的值,不然拋出異常。
該方法的參數是一個lamda
表達式。這裏就不深究lamda
表達式的幾種類型了,若是感興趣能夠自行研究下Function
、Consumer
、Predicate
、Supplier
這四個函數式接口的區別。
因此傳一個lamda
表達式進去,而後IDEA
會給出警告:
Can be replaced with method reference
該lamda
表達式能被一個方法引用代替,Alt + Enter
,咱們最終的代碼就長這樣:
這裏的::
是lamda
表達式的一種簡寫,是Java8
中的新特性,看着可能有點奇怪,原來,編譯器比程序員聰明多了。
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity<String> entityNotFoundHandler() { return new ResponseEntity<>("您要找的實體不存在", HttpStatus.NOT_FOUND); } }
寫個控制器加強,全局處理異常,這裏的RestControllerAdvice
又是一個組合註解:
處理異常,同時以Json
的格式返回。
@Test public void findById() throws Exception { this.mockMvc.perform(get("/cat/1")) .andDo(print()); }
寫個控制器的單元測試,查詢一個不存在的實體,運行,看控制檯的打印輸出:
一勞永逸,這是咱們最喜歡的東西了。
return catRepository.findById(id).orElseThrow(EntityNotFoundException::new);
之後再查詢,就這一行,不再用去判斷null
了。
正所謂條條大路通羅馬,對null
的一勞永逸,咱們這樣實現,別人也能夠那樣實現。
若是你在Spring
的項目中打過斷點調試的話,那我判定你必定見過下面這行代碼:
Assert.notNull();
如下是該方法的源碼,注意這裏的Assert
是org.springframework.util
包下的:
剛方法用於判斷null
,若是爲空,則拋出異常。
隨便點開一個方法,都會在第一行爲不應爲null
的參數進行判斷。
這裏,不由對整個框架肅然起敬。
以前一直抱怨Java
更新的太快:
其實,Java
的每次更新,都是爲了咱們更簡潔優雅的代碼而努力。去看看官方的描述,Java
讓咱們將更多的精力放在think
上,而不是code
上。