1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 2778字,需瀏覽 6分鐘

         ·

        2020-10-14 04:46

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



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

        /**

        *?@author?Axin

        *?@since?2020-09-20

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

        ?*?(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)行判空,雖然有些麻煩,到也能用,通過(guò) JDK8 提供的 Optional 工具也是可以,但還是有些麻煩。
        而下文的 OptionalBean 提供一種可以鏈?zhǔn)讲粩嗟卣{(diào)用成員變量而無(wú)需判空的方法,直接鏈?zhǔn)秸{(diào)用到你想要獲取的目標(biāo)變量,而無(wú)需擔(dān)心空指針的問(wè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變量為空,可以看到代碼并沒(méi)有空指針,而是返回了null。這個(gè)工具怎么實(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;

        ????}

        ????/**

        ?????*?空值會(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)值為空?通過(guò)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ì)象成員而無(wú)需判空的工具讓代碼更加的精準(zhǔn)和優(yōu)雅,如果本文設(shè)計(jì)的工具滿(mǎn)足了剛好解決你的困擾,那就在項(xiàng)目中使用吧!
        如果您有更的設(shè)計(jì)或者文中有錯(cuò)誤,還請(qǐng)留言一起討論,互相進(jìn)步!



        往期推薦

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


        2.5 億!華為成立新公司!


        Mozilla,一個(gè)被遺忘的偉大科技的公司!


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

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

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


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

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美超级操逼视频免费观看 | 黄色视频网站日本 | 国内拍自拍偷自拍视频2022 | 91亚洲精品一区二区乱码 | 一级内射视频 | 91久久免费| 色图国产| 午夜精品久久久久久不卡8050 | 国产欧美岛国 | 国产精品视频福利 |