摘要:實踐很簡單的一個類,點開它的源代碼,其中所有的方法都是與相關(guān)聯(lián)的。從而很好地避免了空指針異常。方法,如果存在,返回包含的值,否則拋出異常。隨便點開一個方法,都會在第一行為不該為的參數(shù)進行判斷。
問題描述
在大熱的Spring Boot 2.0中,在將原來的泛型改為了Optional,旨在讓我們的代碼更簡潔。
實踐 Optional很簡單的一個類,點開它的源代碼,其中所有的方法都是與null相關(guān)聯(lián)的。
這是一個簡化我們處理null的類。
它就是一個容器,其中有我們想要的對象,但是該對象有時候會是空,所以我們需要使用Optional封裝好的方法來獲取需要的對象。從而很好地避免了空指針異常。
錯誤示范我看到網(wǎng)上很多人這么寫:
catRepository.findById(id).get();
下面是Spring Boot 1.5的寫法,那請問:如果上面的寫法是正確的,那為什么還要大費周章設(shè)計一個Optional呢?
catRepository.findOne(id);分析
通過get是能獲取到我們需要的對象。
但是看看get的源代碼,這樣寫,拋出了NoSuchElementException異常,這個異常我們沒法在全局中處理它。
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; }
為什么不能再全局中處理呢?大家可以思考一下:
因為NoSuchElementException覆蓋的范圍太廣了,只要是Optional中有null就會拋出NoSuchElementException,很多情況下都會造成這種異常,那我們究竟要給用戶一個什么樣的提示信息好呢?最后還是給出500服務器異常,那異常處理的意義何在呢?
所以我們需要用Optional來拋出一個有特定范圍的能被全局準確處理的異常。
Cat cat = catRepository.findOne(id); if (null == cat) { throw new EntityNotFoundException("該實體找不到"); } return cat;
思想都是一樣,我們不過是用一種更簡潔的寫法實現(xiàn)上面的功能。
實現(xiàn)沒錯,就像下面一樣,我們只需要一行代碼!
public Cat findById(Long id) { return catRepository.findById(id).orElseThrow(EntityNotFoundException::new); }
findById返回一個Optional,然后調(diào)用該對象的orElseThrow方法。
orElseThrow方法,如果存在,返回包含的值,否則拋出異常。
該方法的參數(shù)是一個lamda表達式。這里就不深究lamda表達式的幾種類型了,如果感興趣可以自行研究下Function、Consumer、Predicate、Supplier這四個函數(shù)式接口的區(qū)別。
所以傳一個lamda表達式進去,然后IDEA會給出警告:
Can be replaced with method reference
該lamda表達式能被一個方法引用代替,Alt + Enter,我們最終的代碼就長這樣:
這里的::是lamda表達式的一種簡寫,是Java8中的新特性,看著可能有點奇怪,原來,編譯器比程序員聰明多了。
異常處理@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) public ResponseEntityentityNotFoundHandler() { 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了。
NotNull正所謂條條大路通羅馬,對null的一勞永逸,我們這樣實現(xiàn),別人也可以那樣實現(xiàn)。
如果你在Spring的項目中打過斷點調(diào)試的話,那我斷定你一定見過下面這行代碼:
Assert.notNull();
以下是該方法的源碼,注意這里的Assert是org.springframework.util包下的:
剛方法用于判斷null,如果為空,則拋出異常。
隨便點開一個方法,都會在第一行為不該為null的參數(shù)進行判斷。
這里,不禁對整個框架肅然起敬。
總結(jié)之前一直抱怨Java更新的太快:
其實,Java的每次更新,都是為了我們更簡潔優(yōu)雅的代碼而努力。去看看官方的描述,Java讓我們將更多的精力放在think上,而不是code上。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77239.html
摘要:當滿足條件時執(zhí)行傳入的參數(shù)化操作。最后提醒一點,好用但不能濫用,在設(shè)計一個接口方法時是否采取類型返回需要斟酌,一味的使用會讓代碼變得比較啰嗦,反而破壞了代碼的簡潔性。鑒于作者水平有限,文中不免有錯誤之處,歡迎批評指正個人博客 NullPointException 可以說是所有 java 程序員都遇到過的一個異常,雖然 java 從設(shè)計之初就力圖讓程序員脫離指針的苦海,但是指針確實是實際...
摘要:新特性總覽標簽本文主要介紹的新特性,包括表達式方法引用流默認方法組合式異步編程新的時間,等等各個方面。還有對應的和類型的函數(shù)連接字符串廣義的歸約匯總起始值,映射方法,二元結(jié)合二元結(jié)合。使用并行流時要注意避免共享可變狀態(tài)。 Java8新特性總覽 標簽: java [TOC] 本文主要介紹 Java 8 的新特性,包括 Lambda 表達式、方法引用、流(Stream API)、默認方...
摘要:是第一批在堆上分配記錄的類型語言之一。實際上,的這段話低估了過去五十年來數(shù)百萬程序員為修復空引用所耗費的代價。很明顯,這種方式不具備擴展性,同時還犧牲了代碼的可讀性。是目前程序開發(fā)中最典型的異常。完成這一任務有多種方法。 用Optional取代null 如果你作為Java程序員曾經(jīng)遭遇過NullPointerException,請舉起手。如果這是你最常遭遇的異常,請繼續(xù)舉手。非常可惜,...
摘要:近日,在上列舉了開發(fā)中常見的個錯誤,與君共免。在多線程中并發(fā)修改集合內(nèi)容是非常常見的,因此需要使用并發(fā)編程中常用的方法進行處理,例如同步鎖對于并發(fā)修改采用特殊的集合等等。在單線程和多線程情況下解決這個問題有微小的差別。 在編程時,開發(fā)者經(jīng)常會遭遇各式各樣莫名錯誤。近日,Sushil Das 在 Geek On Java上列舉了 Java 開發(fā)中常見的 5 個錯誤,與君共「免」。 原文...
摘要:于是,在引入了,用來代表一種可能有可能沒有的數(shù)據(jù),可以用來緩解空指針異常的問題。 一位智者說過,沒有處理過空指針異常就不算一個真正的 Java 程序員。這當然是開玩笑,但是空指針異常確實是很多程序出錯的源頭。于是,在 Java 8 引入了 java.util.Optional,Optional 用來代表一種 可能有可能沒有 的數(shù)據(jù),可以用來緩解空指針異常的問題。 簡單地說,Option...
閱讀 813·2021-11-18 10:02
閱讀 2503·2021-11-11 16:54
閱讀 2750·2021-09-02 09:45
閱讀 654·2019-08-30 12:52
閱讀 2774·2019-08-29 14:04
閱讀 2745·2019-08-29 12:39
閱讀 448·2019-08-29 12:27
閱讀 1887·2019-08-26 13:23