Java 如何避免寫嵌套if樣式的代碼

原文地址
Optional的代碼相對更加簡潔,當代碼量較大時抛猖,我們很容易忘記進行null判定乔煞,但是使用Optional類則會避免這類問題。

下面這是一個嵌套的 if 判斷,業(yè)務(wù)邏輯是從 httpRequst 中獲取 X-Auth-Token 的值忍啤。邏輯是如果 header中有值則從 header 中取值否則從 cookie 中取值,取到值后調(diào)用一個 http 遠程接口 獲取用戶信息,獲取不到則報“獲取用戶信息失敗”,如果 token 都不存在則直接返回 httpRespons 為 401-NoAuth

這下面是之前同事寫的代碼

if 嵌套代碼

if (methodNeedAuth) {
    //***身份驗證
    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);
        } //這個地方判空,否則下面的 Arrays.stream 回報空指針異常
        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) {
    //***身份驗證
    String token = Optional.ofNullable(request.getHeader("X-Auth-Token")).orElseGet(() ->
            getTokenFromCookie(request) //提取出一個方法
    );
    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 強制賦默認值,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ī)避所有的空指針異常問題么?答案當然是否定的, Optional<T>() 也是對象,他也會為 null, 所以也有可能報空指針異常喲仙辟。

Optional 的三種構(gòu)造方式: Optional.of(obj), Optional.ofNullable(obj) 和明確的 Optional.empty()

  1. Optional.of(obj): 它要求傳入的 obj 不能是 null 值的, 否則還沒開始進入角色就倒在了 NullPointerException 異常上了.
  2. Optional.ofNullable(obj): 它以一種智能的, 寬容的方式來構(gòu)造一個 Optional 實例. 來者不拒, 傳 null 進到就得到 Optional.empty(), 非 null 就調(diào)用 Optional.of(obj).

那是不是我們只要用 Optional.ofNullable(obj) 一勞永逸, 以不變應(yīng)二變的方式來構(gòu)造 Optional 實例就行了呢? 那也未必, 否則 Optional.of(obj) 何必如此暴露呢, 私有則可?
我本人的觀點是:

  1. 當我們非常非常的明確將要傳給 Optional.of(obj) 的 obj 參數(shù)不可能為 null 時, 比如它是一個剛 new 出來的對象(Optional.of(new User(...))), 或者是一個非 null 常量時;
  2. 當想為 obj 斷言不為 null 時, 即我們想在萬一 obj 為 null 立即報告 NullPointException 異常, 立即修改, 而不是隱藏空指針異常時, 我們就應(yīng)該果斷的用 Optional.of(obj) 來構(gòu)造 Optional 實例, 而不讓任何不可預計的 null 值有可乘之機隱身于 Optional 中.

Java8 Optional需要小心的地方

  1. 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 不包含一個值, get() 將會拋出一個異常)
  2. Reports any uses of java.util.Optional<T>, 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è)計為類庫方法的, 可明確表示可能無值情況下的返回類型. Optional 類型不可被序列化, 用作字段類型會出問題的)

一句話小結(jié): 使用 Optional 時盡量不直接調(diào)用 Optional.get() 方法, Optional.isPresent() 更應(yīng)該被視為一個私有方法, 應(yīng)依賴于其他像 Optional.orElse(), Optional.orElseGet(), Optional.map() 等這樣的方法.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末同波,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叠国,更是在濱河造成了極大的恐慌未檩,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粟焊,死亡現(xiàn)場離奇詭異冤狡,居然都是意外死亡,警方通過查閱死者的電腦和手機吆玖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門筒溃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沾乘,你說我怎么就攤上這事』氩猓” “怎么了翅阵?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長迁央。 經(jīng)常有香客問我掷匠,道長,這世上最難降的妖魔是什么岖圈? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任讹语,我火速辦了婚禮,結(jié)果婚禮上蜂科,老公的妹妹穿的比我還像新娘顽决。我一直安慰自己,他們只是感情好导匣,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布才菠。 她就那樣靜靜地躺著,像睡著了一般贡定。 火紅的嫁衣襯著肌膚如雪赋访。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音蚓耽,去河邊找鬼渠牲。 笑死,一個胖子當著我的面吹牛步悠,可吹牛的內(nèi)容都是我干的嘱兼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼贤徒,長吁一口氣:“原來是場噩夢啊……” “哼芹壕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起接奈,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤踢涌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后序宦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睁壁,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年互捌,在試婚紗的時候發(fā)現(xiàn)自己被綠了潘明。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡秕噪,死狀恐怖钳降,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腌巾,我是刑警寧澤遂填,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站澈蝙,受9級特大地震影響吓坚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜灯荧,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一礁击、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逗载,春花似錦哆窿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捏膨,卻和暖如春秧均,著一層夾襖步出監(jiān)牢的瞬間食侮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工目胡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锯七,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓誉己,卻偏偏與公主長得像眉尸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子巨双,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理噪猾,服務(wù)發(fā)現(xiàn),斷路器筑累,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗袱蜡。 張土汪:刷leetcod...
    土汪閱讀 12,743評論 0 33
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法慢宗,內(nèi)部類的語法坪蚁,繼承相關(guān)的語法,異常的語法镜沽,線程的語...
    子非魚_t_閱讀 31,622評論 18 399
  • 最近Kimi的消息刷爆了微博和朋友圈敏晤,也讓抑郁癥得到了大家的關(guān)注。朋友發(fā)來的專業(yè)測試缅茉,我還沒測嘴脾,就看到她艾特我的消...
    訫心怡閱讀 232評論 0 0
  • 一道阿拉伯甜品:“阿里的母親” 牛乳與奶酪融合的絲滑奶香,手制面包軟糯也帶著勁道的嚼勁宾舅。 甜到剛好统阿,輔佐飽滿酸甘的...
    蛋黃醬瑪幽閱讀 230評論 0 0