<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>

          求求你,不要再使用!=null判空了!

          共 2666字,需瀏覽 6分鐘

           ·

          2020-12-05 22:21

          對(duì)于Java程序員來說,null是令人頭痛的東西。時(shí)常會(huì)受到空指針異常(NPE)的騷擾。連Java的發(fā)明者都承認(rèn)這是他的一項(xiàng)巨大失誤。
          那么,有什么辦法可以避免在代碼中寫大量的判空語句呢?
          有人說可以使用 JDK8提供的 Optional 來避免判空,但是用起來還是有些麻煩。
          作者在日常工作中,封裝了一個(gè)工具,可以可以鏈?zhǔn)秸{(diào)用對(duì)象成員而無需判空,相比原有的if null邏輯 和 JDK8提供的 Optional 更加優(yōu)雅易用,在工程實(shí)踐中大大提高了編碼效率,也讓代碼更加的精準(zhǔn)和優(yōu)雅。



          不優(yōu)雅的判空調(diào)用
          我想從事Java開發(fā)的小伙伴肯定有遇到過下面這種讓人難受的判空邏輯:現(xiàn)在有一個(gè)User類,School 是它的成員變量

          /**

          *?@author?Axin

          *?@since?2020-09-20

          *?@summary?一個(gè)User類定義

          ?*?(Ps:Data 是lombok組件提供的注解,簡(jiǎn)化了get set等等的約定代碼)

          */


          @Data

          public?class?User?{

          ????private?String?name;

          ????private?String?gender;

          ????private?School?school;

          ????@Data

          ????public?static?class?School?{

          ????????private?String?scName;

          ????????private?String?adress;

          ????}

          }

          現(xiàn)在想要獲得School的成員變量 adress , 一般的處理方式:

          public?static?void?main(String[]?args)?{

          ????User?axin?=?new?User();

          ????User.School?school?=?new?User.School();

          ????axin.setName("hello");

          ????if?(Objects.nonNull(axin)?&&?Objects.nonNull(axin.getSchool()))?{

          ????????User.School?userSc?=?axin.getSchool();

          ????????System.out.println(userSc.getAdress());

          ????}

          }

          獲取adress時(shí)要對(duì)School進(jìn)行判空,雖然有些麻煩,到也能用,通過 JDK8 提供的 Optional 工具也是可以,但還是有些麻煩。
          而下文的 OptionalBean 提供一種可以鏈?zhǔn)讲粩嗟卣{(diào)用成員變量而無需判空的方法,直接鏈?zhǔn)秸{(diào)用到你想要獲取的目標(biāo)變量,而無需擔(dān)心空指針的問題。



          鏈?zhǔn)秸{(diào)用成員變量
          如果用了本文設(shè)計(jì)的工具 OptionalBean ,那么上述的調(diào)用可以簡(jiǎn)化成這樣:

          public?static?void?main(String[]?args)?{

          ????User?axin?=?new?User();

          ????User.School?school?=?new?User.School();

          ????axin.setName("hello");

          ????//?1.?基本調(diào)用

          ????String?value1?=?OptionalBean.ofNullable(axin)

          ????????????.getBean(User::getSchool)

          ????????????.getBean(User.School::getAdress).get();

          ????System.out.println(value1);

          }

          執(zhí)行結(jié)果:
          其中User的school變量為空,可以看到代碼并沒有空指針,而是返回了null。這個(gè)工具怎么實(shí)現(xiàn)的呢?



          OptionalBean 工具

          /**

          *?@author?Axin

          *?@since?2020-09-10

          *?@summary?鏈?zhǔn)秸{(diào)用?bean?中?value?的方法

          */


          public?final?class?OptionalBean{

          ????
          private?static?final?OptionalBean?EMPTY?=?new?OptionalBean<>();

          ????
          private?final?T?value;

          ????
          private?OptionalBean()?{

          ????????
          this.value?=?null;

          ????}

          ????
          /**

          ?????*?空值會(huì)拋出空指針

          ?????*?@param?value

          ?????*/


          ????
          private?OptionalBean(T?value)?{

          ????????
          this.value?=?Objects.requireNonNull(value);

          ????}

          ????
          /**

          ?????*?包裝一個(gè)不能為空的?bean

          ?????*?@param?value

          ?????*?@param?

          ?????*?@return

          ?????*/


          ????
          public?static??OptionalBean?of(T?value)?{

          ????????
          return?new?OptionalBean<>(value);

          ????}

          ????
          /**

          ?????*?包裝一個(gè)可能為空的?bean

          ?????*?@param?value

          ?????*?@param?

          ?????*?@return

          ?????*/


          ????
          public?static??OptionalBean?ofNullable(T?value)?{

          ????????
          return?value?==?null???empty()?:?of(value);

          ????}

          ????
          /**

          ?????*?取出具體的值

          ?????*?@param?fn

          ?????*?@param?

          ?????*?@return

          ?????*/


          ????
          public?T?get()?{

          ????????
          return?Objects.isNull(value)???null?:?value;

          ????}

          ????
          /**

          ?????*?取出一個(gè)可能為空的對(duì)象

          ?????*?@param?fn

          ?????*?@param?>

          ?????*?@return

          ?????*/


          ????
          public?>?OptionalBean>?getBean(Functionsuper?T,???extends?R>?fn)?{

          ????????
          return?Objects.isNull(value)???OptionalBean.empty()?:?OptionalBean.ofNullable(fn.apply(value));

          ????}

          ????
          /**

          ?????*?如果目標(biāo)值為空?獲取一個(gè)默認(rèn)值

          ?????*?@param?other

          ?????*?@return

          ?????*/


          ????
          public?T?orElse(T?other)?{

          ????????
          return?value?!=?null???value?:?other;

          ????}

          ????
          /**

          ?????*?如果目標(biāo)值為空?通過lambda表達(dá)式獲取一個(gè)值

          ?????*?@param?other

          ?????*?@return

          ?????*/


          ????
          public?T?orElseGet(Supplier other)?{

          ????????
          return?value?!=?null???value?:?other.get();

          ????}

          ????
          /**

          ?????*?如果目標(biāo)值為空?拋出一個(gè)異常

          ?????*?@param?exceptionSupplier

          ?????*?@param?

          ?????*?@return

          ?????*?@throws?X

          ?????*/


          ????
          public??T?orElseThrow(Supplier?exceptionSupplier)?throws?X?{

          ????????
          if?(value?!=?null)?{

          ????????????
          return?value;

          ????????}?
          else?{

          ????????????
          throw?exceptionSupplier.get();

          ????????}

          ????}

          ????
          public?boolean?isPresent()?{

          ????????
          return?value?!=?null;

          ????}

          ????
          public?void?ifPresent(Consumersuper?T> consumer)?
          {

          ????????
          if?(value?!=?null)

          ????????????consumer.accept(value);

          ????}

          ????
          @Override

          ????
          public?int?hashCode()?{

          ????????
          return?Objects.hashCode(value);

          ????}

          ????
          /**

          ?????*?空值常量

          ?????*?@param?

          ?????*?@return

          ?????*/


          ????
          public?static?OptionalBean?empty()?{

          ????????
          @SuppressWarnings("unchecked")

          ????????OptionalBean?none?=?(OptionalBean)?EMPTY;

          ????????
          return?none;

          ????}

          }

          工具設(shè)計(jì)主要參考了 Optional 的實(shí)現(xiàn),再加上對(duì)鏈?zhǔn)秸{(diào)用的擴(kuò)展就是上述的OptionalBean。
          getBean 其實(shí)是當(dāng)變量為空時(shí)返回了一個(gè) 包裝空值的 OptionalBean 對(duì)象,同時(shí)泛型的使用讓工具更加易用。



          使用手冊(cè)
          可以看到代碼中也提供了和 Optional 一樣的擴(kuò)展方法,如 ifPresent()、orElse()等等:

          public?static?void?main(String[]?args)?{

          ????User?axin?=?new?User();

          ????User.School?school?=?new?User.School();

          ????axin.setName("hello");

          ????//?1.?基本調(diào)用

          ????String?value1?=?OptionalBean.ofNullable(axin)

          ????????????.getBean(User::getSchool)

          ????????????.getBean(User.School::getAdress).get();

          ????System.out.println(value1);

          ????//?2.?擴(kuò)展的?isPresent方法?用法與?Optional?一樣

          ????boolean?present?=?OptionalBean.ofNullable(axin)

          ????????????.getBean(User::getSchool)

          ????????????.getBean(User.School::getAdress).isPresent();

          ????System.out.println(present);

          ????//?3.?擴(kuò)展的?ifPresent?方法

          ????OptionalBean.ofNullable(axin)

          ????????????.getBean(User::getSchool)

          ????????????.getBean(User.School::getAdress)

          ????????????.ifPresent(adress?->?System.out.println(String.format("地址存在:%s",?adress)));

          ????//?4.?擴(kuò)展的?orElse

          ????String?value2?=?OptionalBean.ofNullable(axin)

          ????????????.getBean(User::getSchool)

          ????????????.getBean(User.School::getAdress).orElse("家里蹲");

          ????System.out.println(value2);

          ????//?5.?擴(kuò)展的?orElseThrow

          ????try?{

          ????????String?value3?=?OptionalBean.ofNullable(axin)

          ????????????????.getBean(User::getSchool)

          ????????????????.getBean(User.School::getAdress).orElseThrow(()?->?new?RuntimeException("空指針了"));

          ????}?catch?(Exception?e)?{

          ????????System.out.println(e.getMessage());

          ????}

          }

          run一下:



          總結(jié)
          設(shè)計(jì)了一種可以鏈?zhǔn)秸{(diào)用對(duì)象成員而無需判空的工具讓代碼更加的精準(zhǔn)和優(yōu)雅,如果本文設(shè)計(jì)的工具滿足了剛好解決你的困擾,那就在項(xiàng)目中使用吧!
          如果您有更的設(shè)計(jì)或者文中有錯(cuò)誤,還請(qǐng)留言一起討論,互相進(jìn)步!

          往期推薦

          這8種常見的SQL錯(cuò)誤用法,你還在用嗎?


          千萬不要這樣寫代碼!9種常見的OOM場(chǎng)景演示


          用好MySQL的21個(gè)好習(xí)慣!


          關(guān)注我,每天陪你進(jìn)步一點(diǎn)點(diǎn)!

          瀏覽 30
          點(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>
                  日本亚洲免费视频 | 成人乱无码AV在线观看 | 欧美人妻日韩视频 | 草逼操| 天天添夜夜干 |