<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判空了!

          共 2778字,需瀏覽 6分鐘

           ·

          2020-10-14 04:46

          △Hollis, 一個對Coding有著獨(dú)特追求的人△
          這是Hollis的第?307?篇原創(chuàng)分享
          作者 l?上帝愛吃蘋果
          來源 l Hollis(ID:hollischuang)
          本文來自作者投稿,原作者:上帝愛吃蘋果
          對于Java程序員來說,null是令人頭痛的東西。時常會受到空指針異常(NPE)的騷擾。連Java的發(fā)明者都承認(rèn)這是他的一項巨大失誤。
          那么,有什么辦法可以避免在代碼中寫大量的判空語句呢?
          有人說可以使用 JDK8提供的 Optional 來避免判空,但是用起來還是有些麻煩。
          作者在日常工作中,封裝了一個工具,可以可以鏈?zhǔn)秸{(diào)用對象成員而無需判空,相比原有的if null邏輯 和 JDK8提供的 Optional 更加優(yōu)雅易用,在工程實(shí)踐中大大提高了編碼效率,也讓代碼更加的精準(zhǔn)和優(yōu)雅。



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

          /**

          *?@author?Axin

          *?@since?2020-09-20

          *?@summary?一個User類定義

          ?*?(Ps:Data 是lombok組件提供的注解,簡化了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時要對School進(jìn)行判空,雖然有些麻煩,到也能用,通過 JDK8 提供的 Optional 工具也是可以,但還是有些麻煩。
          而下文的 OptionalBean 提供一種可以鏈?zhǔn)讲粩嗟卣{(diào)用成員變量而無需判空的方法,直接鏈?zhǔn)秸{(diào)用到你想要獲取的目標(biāo)變量,而無需擔(dān)心空指針的問題。



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

          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。這個工具怎么實(shí)現(xiàn)的呢?



          OptionalBean 工具

          /**

          *?@author?Axin

          *?@since?2020-09-10

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

          */


          public?final?class?OptionalBean&lt;T>?{

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

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

          ????private?OptionalBean()?{

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

          ????}

          ????/**

          ?????*?空值會拋出空指針

          ?????*?@param?value

          ?????*/


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

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

          ????}

          ????/**

          ?????*?包裝一個不能為空的?bean

          ?????*?@param?value

          ?????*?@param?

          ?????*?@return

          ?????*/


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

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

          ????}

          ????/**

          ?????*?包裝一個可能為空的?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;

          ????}

          ????/**

          ?????*?取出一個可能為空的對象

          ?????*?@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)值為空?獲取一個默認(rèn)值

          ?????*?@param?other

          ?????*?@return

          ?????*/


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

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

          ????}

          ????/**

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

          ?????*?@param?other

          ?????*?@return

          ?????*/


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

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

          ????}

          ????/**

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

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



          使用手冊
          可以看到代碼中也提供了和 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è)計了一種可以鏈?zhǔn)秸{(diào)用對象成員而無需判空的工具讓代碼更加的精準(zhǔn)和優(yōu)雅,如果本文設(shè)計的工具滿足了剛好解決你的困擾,那就在項目中使用吧!
          如果您有更的設(shè)計或者文中有錯誤,還請留言一起討論,互相進(jìn)步!



          往期推薦

          已經(jīng)是最大股東卻還要全資收購!騰訊看上了搜狗的啥?


          2.5 億!華為成立新公司!


          Mozilla,一個被遺忘的偉大科技的公司!


          本文由“壹伴編輯器”提供技術(shù)支
          ?

          直面Java第329期:哪個命令可以監(jiān)控虛擬機(jī)各種運(yùn)行狀態(tài)信息?

          深入并發(fā)第013期:拓展synchronized——鎖優(yōu)化


          如果你喜歡本文,
          請長按二維碼,關(guān)注?Hollis.
          轉(zhuǎn)發(fā)至朋友圈,是對我最大的支持。

          點(diǎn)個?在看?
          喜歡是一種感覺
          在看是一種支持
          ↘↘↘
          瀏覽 30
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  俺去也俺也去 | 亚洲男女内射 | 亚洲少妇六区 | 疯狂做爰XXXⅩa久久久久久 | 99在线视频精品 |