<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          公司剛?cè)肼毩艘幻屑?jí)Java開(kāi)發(fā),短短4行代碼居然湊齊了3個(gè)bug!我...

          共 2572字,需瀏覽 6分鐘

           ·

          2022-09-29 01:42

          一、前言

          Hello 大家好,我是團(tuán)長(zhǎng),今天帶來(lái)一個(gè)真實(shí)案例,讓大家更深刻的理解空指針異常。

          公司剛?cè)肼毩艘幻屑?jí)Java開(kāi)發(fā),經(jīng)過(guò)一個(gè)星期的適應(yīng)學(xué)習(xí),各方面表現(xiàn)還不錯(cuò),于是分配了一個(gè)小的迭代給新人做。

          需求很簡(jiǎn)單,把從第三方拉取的數(shù)據(jù)匹配到自身公司后臺(tái)設(shè)置的渠道后,聚合到一個(gè)列表中,批量入庫(kù)。

          然而就在匹配的邏輯中,上線(xiàn)后報(bào)了個(gè)NPE,這是作為一名中級(jí)開(kāi)發(fā)不應(yīng)犯的簡(jiǎn)單錯(cuò)誤,新人被我狠狠的訓(xùn)了,記生產(chǎn)事故一次。

          二、事故重現(xiàn)

          1、偽代碼

          說(shuō)明:偽代碼并非真實(shí)線(xiàn)上代碼,只是為了更方便,更形象的重現(xiàn)事故現(xiàn)場(chǎng)而編寫(xiě)的;真實(shí)的業(yè)務(wù)場(chǎng)景往往更加復(fù)雜,NPE的漏洞隱藏在更深處,不易code view出來(lái),也不易測(cè)試出來(lái);生產(chǎn)環(huán)境NPE是較常見(jiàn)的異常,希望大家不要糾結(jié)為什么測(cè)試沒(méi)測(cè)出來(lái),關(guān)鍵還是通過(guò)這樣一個(gè)案例了解NPE的原因和解決方案。

                
                //?后臺(tái)設(shè)置的渠道
          String?channelNo?=?channelDao.getOne().getChannelNo();
          //?第三方拉取的數(shù)據(jù)
          List<ThirdData>?thirdDataList?=?httpClientUtils.getThirdDatas(DateUtils.today());
          //?匹配過(guò)濾
          thirdDataList.stream().filter(o?->channelNo.equals(o.getChannelNo())).collect(Collectors.toList());
          //?批量入庫(kù)
          thirdDataDao.saveAll(thirdDataList);

          2、分析與解決

          有經(jīng)驗(yàn)、技術(shù)扎實(shí)的同學(xué)看到這里應(yīng)該或多或少能發(fā)現(xiàn)問(wèn)題了。其實(shí)啊,這四段代碼是作者精心設(shè)計(jì)的,可謂是臥龍鳳雛。

          短短四行代碼居然湊齊了3個(gè)NPE,我枯了~~

          我們逐行分析:

          3、第一行分析

          channelDao.getOne()如果返回為null,那么調(diào)用getChannelNo()會(huì)報(bào)NPE。

          4、解決辦法

          1、使用防御性編程,提前返回(需根據(jù)具體業(yè)務(wù)場(chǎng)景而定)

                
                //?如果channelNo是方法邏輯執(zhí)行的必須元素,推薦用此方法
          Channel?channel?=?channelDao.getOne();
          if?(channel?==?null)?{
          ????return;
          }

          2、使用三目運(yùn)算,返回空字符串("")

                
                //?返回兜底的空字符串
          String?channelNo?=?channelDao.getOne()?==?null???""?:?channelDao.getOne().getChannelNo();

          3、使用Optional函數(shù),返回空字符串("")

                
                String?channelNo?=?Optional.ofNullable(channelDao.getOne()).orElse("");

          5、第三行分析(1)

          thirdDataList如果為null,那么調(diào)用stream()會(huì)報(bào)NPE。

          通過(guò)下面的源碼截圖就能知道原因:

          b939d4e3b147d89fee73bc6935c8b55d.webp09d1a10bfcda942c065dc1628a3641e7.webp

          6、解決辦法

          1、使用防御性編程,提前返回(推薦)

                
                //?推薦使用集合工具類(lèi)判空
          if?(CollectionUtils.isEmpty(thirdDataList))?{
          ????return;
          }

          2、使用if條件語(yǔ)句包裹(不推薦)

                
                if?(CollectionUtils.isNotEmpty(thirdDataList))?{
          ????//?執(zhí)行后面的邏輯
          }

          7、第三行分析(2)

          channelNo如果返回為null,那么執(zhí)行channelNo.equals(o.getChannelNo())會(huì)報(bào)NPE。

          我們知道,按Java的規(guī)范String的equals()方法的調(diào)用,要求左邊是確定值,就是為了避免調(diào)用方為null的情況。然而這里調(diào)用方和equals的入?yún)⒍际亲兞?,這種情況該怎么辦呢?

          1、再加一句判斷:

                
                channelNo?!=?null?&&?channelNo.equals(o.getChannelNo())

          2、其實(shí)可以用java.uti包下的Objects類(lèi)的equals方法

                
                Objects.equals(channelNo,?o.getChannelNo())

          看源碼一目了然,該方法對(duì)左邊的對(duì)象做了非空判斷

          7825669ce8b61f454ec8a7ed89e6753c.webp

          3、用其他開(kāi)源的工具類(lèi)庫(kù)或者自己實(shí)現(xiàn)

          如:

                
                org.apache.commons.lang3.StringUtils
          cn.hutool.core.util.StrUtil;

          最后

          在這里團(tuán)長(zhǎng)要推薦一款I(lǐng)DEA的插件:

          需要開(kāi)通正版IDEA的可以加我微信:poxiaozhiai6,56元一年。

          這款插件就是:SonarLint

          a52f4c7183d375ae5ff42521dedd5724.webp

          能動(dòng)態(tài)的幫您檢查代碼漏洞,像NPE這種代碼風(fēng)險(xiǎn)都會(huì)給于相應(yīng)的提示。

          SonarLint還有一個(gè)大名鼎鼎的服務(wù)端叫SonarQube。

          碼字不易,望多多在看、多多點(diǎn)贊??



          原文鏈接:juejin.cn/post/7031445206152577061 原文作者:l拉不拉米
          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  蜜桃无码 | 精品+国产+内射 | 日韩尤物在线播放 | 国产婷婷色一区二区三区 | 怕怕怕视频网站 |