Java中避免寫嵌套if樣式的代碼詳解
前言
Optional的代碼相對更加簡潔,當(dāng)代碼量較大時(shí),我們很容易忘記進(jìn)行null判定,但是使用Optional類則會避免這類問題。
下面這是一個(gè)嵌套的 if 判斷,業(yè)務(wù)邏輯是從 httpRequst 中獲取 X-Auth-Token 的值。邏輯是如果 header中有值則從 header 中取值否則從 cookie 中取值,取到值后調(diào)用一個(gè) http 遠(yuǎn)程接口 獲取用戶信息,獲取不到則報(bào)“獲取用戶信息失敗”,如果 token 都不存在則直接返回 httpRespons 為 401-NoAuth
這下面是之前同事寫的代碼
if 嵌套代碼
if (methodNeedAuth) { //***身份驗(yàn)證 String token = request.getHeader("X-Auth-Token"); if (StringUtils.isEmpty(token)) { // 如果 header 中沒有 X-Auth-Token 則從 cookie 中取 Cookie[] cookies = request.getCookies(); if (cookies == null || cookies.length == 0) { //cookie 都為 null return returnNoAuthResult(response); } //這個(gè)地方判空,否則下面的 Arrays.stream 回報(bào)空指針異常 token = Arrays.stream(cookies).filter(cookie -> "X-Auth-Token".equals(cookie.getName()) ).collect(Collectors.toList()).get(0).getValue(); if (token == null) { // cookie 有值但是 cookie 中沒有 X-Auth-Token return returnNoAuthResult(response); } } if (!StringTool.isNullOrEmpty(token)) { userInfo = userService.getUserInfoByToken(token); } if (userInfo == null || StringTool.isNullOrEmpty(userInfo.getUser_id())) { return returnNoAuthResult(response); } }
Optional 規(guī)避 if 嵌套
if (methodNeedAuth) { //***身份驗(yàn)證 String token = Optional.ofNullable(request.getHeader("X-Auth-Token")).orElseGet(() -> getTokenFromCookie(request) //提取出一個(gè)方法 ); userInfo = Optional.ofNullable(token).map(Try.of(t -> userService.getUserInfoByToken(t)) ).orElse(null); if (userInfo == null || StringTool.isNullOrEmpty(userInfo.getUser_id())) { response.sendError(401, "no auth"); return false; } } /** * 從 cookie 中獲取 token */ private String getTokenFromCookie(HttpServletRequest request) { Cookie[] cookies = Optional.ofNullable(request.getCookies()).orElse(new Cookie[0]); // Optional 強(qiáng)制賦默認(rèn)值,cookies一定不為 null String cookie = Arrays.stream(cookies).filter(item -> "X-Auth-Token".equals(item.getName()) ).findFirst().map(Cookie::getValue).orElse(null); return cookie; }
小結(jié)
Java8 Optional 的常規(guī)用法
Java8 的 Optional 可以規(guī)避所有的空指針異常問題么?答案當(dāng)然是否定的, Optional<T>()
也是對象,他也會為 null, 所以也有可能報(bào)空指針異常喲。
Optional 的三種構(gòu)造方式: Optional.of(obj), Optional.ofNullable(obj) 和明確的 Optional.empty()
Optional.of(obj)
: 它要求傳入的 obj 不能是 null 值的, 否則還沒開始進(jìn)入角色就倒在了 NullPointerException 異常上了.Optional.ofNullable(obj)
: 它以一種智能的, 寬容的方式來構(gòu)造一個(gè) Optional 實(shí)例. 來者不拒, 傳 null 進(jìn)到就得到Optional.empty()
, 非 null 就調(diào)用Optional.of(obj)
.
那是不是我們只要用 Optional.ofNullable(obj)
一勞永逸, 以不變應(yīng)二變的方式來構(gòu)造 Optional 實(shí)例就行了呢? 那也未必, 否則 Optional.of(obj)
何必如此暴露呢, 私有則可?
我本人的觀點(diǎn)是:
- 當(dāng)我們非常非常的明確將要傳給
Optional.of(obj)
的 obj 參數(shù)不可能為 null 時(shí), 比如它是一個(gè)剛 new 出來的對象(Optional.of(new User(…)))
, 或者是一個(gè)非 null 常量時(shí); - 當(dāng)想為 obj 斷言不為 null 時(shí), 即我們想在萬一 obj 為 null 立即報(bào)告 NullPointException 異常, 立即修改, 而不是隱藏空指針異常時(shí), 我們就應(yīng)該果斷的用
Optional.of(obj)
來構(gòu)造 Optional 實(shí)例, 而不讓任何不可預(yù)計(jì)的 null 值有可乘之機(jī)隱身于 Optional 中.
Java8 Optional需要小心的地方
- Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception. (調(diào)用
Optional.get()
前不事先用isPresent()
檢查值是否可用. 假如 Optional 不包含一個(gè)值, get() 將會拋出一個(gè)異常) - Reports any uses of java.util.Optional, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not. (使用任何像 Optional 的類型作為字段或方法參數(shù)都是不可取的. Optional 只設(shè)計(jì)為類庫方法的, 可明確表示可能無值情況下的返回類型. Optional 類型不可被序列化, 用作字段類型會出問題的)
一句話小結(jié): 使用 Optional 時(shí)盡量不直接調(diào)用 Optional.get()
方法, Optional.isPresent()
更應(yīng)該被視為一個(gè)私有方法, 應(yīng)依賴于其他像 Optional.orElse()
, Optional.orElseGet()
, Optional.map()
等這樣的方法.
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Spring Security實(shí)現(xiàn)禁止用戶重復(fù)登陸的配置原理
這篇文章主要介紹了Spring Security實(shí)現(xiàn)禁止用戶重復(fù)登陸的配置原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12SpringBoot整合Shiro思路(最新超詳細(xì))
這篇文章主要介紹了SpringBoot整合Shiro思路(最新超詳細(xì)),本文內(nèi)容比較長,通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03親手教你IDEA2020.3創(chuàng)建Javaweb項(xiàng)目的步驟詳解
這篇文章主要介紹了IDEA2020.3創(chuàng)建Javaweb項(xiàng)目的步驟詳解,本文是小編手把手教你,通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-03-03Java實(shí)現(xiàn)json數(shù)據(jù)處理的常用腳本分享
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)json數(shù)據(jù)處理的常用腳本,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以學(xué)習(xí)一下2023-03-03Java數(shù)據(jù)結(jié)構(gòu)與算法之選擇排序(動力節(jié)點(diǎn)java學(xué)院整理)
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法之選擇排序的相關(guān)資料,本文通過代碼講解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下2017-04-04詳解spring項(xiàng)目中如何動態(tài)刷新bean
這篇文章主要為大家介紹了詳解spring項(xiàng)目中如何動態(tài)刷新bean,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08