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

        共 2751字,需瀏覽 6分鐘

         ·

        2020-10-29 08:24

        注意文末有最新Java實戰(zhàn)項目面試題


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



        不優(yōu)雅的判空調用
        我想從事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進行判空,雖然有些麻煩,到也能用,通過 JDK8 提供的 Optional 工具也是可以,但還是有些麻煩。
        而下文的 OptionalBean 提供一種可以鏈式不斷地調用成員變量而無需判空的方法,直接鏈式調用到你想要獲取的目標變量,而無需擔心空指針的問題。



        鏈式調用成員變量
        如果用了本文設計的工具 OptionalBean ,那么上述的調用可以簡化成這樣:

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

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

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

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

        ????//?1.?基本調用

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

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

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

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

        }

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



        OptionalBean 工具

        /**

        *?@author?Axin

        *?@since?2020-09-10

        *?@summary?鏈式調用?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));

        ????}

        ????/**

        ?????*?如果目標值為空?獲取一個默認值

        ?????*?@param?other

        ?????*?@return

        ?????*/


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

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

        ????}

        ????/**

        ?????*?如果目標值為空?通過lambda表達式獲取一個值

        ?????*?@param?other

        ?????*?@return

        ?????*/


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

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

        ????}

        ????/**

        ?????*?如果目標值為空?拋出一個異常

        ?????*?@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;

        ????}

        }

        工具設計主要參考了 Optional 的實現(xiàn),再加上對鏈式調用的擴展就是上述的OptionalBean。
        getBean 其實是當變量為空時返回了一個 包裝空值的 OptionalBean 對象,同時泛型的使用讓工具更加易用。



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

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

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

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

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

        ????//?1.?基本調用

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

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

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

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

        ????//?2.?擴展的?isPresent方法?用法與?Optional?一樣

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

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

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

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

        ????//?3.?擴展的?ifPresent?方法

        ????OptionalBean.ofNullable(axin)

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

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

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

        ????//?4.?擴展的?orElse

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

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

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

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

        ????//?5.?擴展的?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一下:



        總結
        設計了一種可以鏈式調用對象成員而無需判空的工具讓代碼更加的精準和優(yōu)雅,如果本文設計的工具滿足了剛好解決你的困擾,那就在項目中使用吧!
        如果您有更的設計或者文中有錯誤,還請留言一起討論,互相進步!
        ---END---
        文末福利



        瀏覽 53
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        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>
            在线不卡中文字幕 | 久久精品欧美 | 国产又大又粗视频 | 亚洲人妻色色 | 国产69精品久久久久777糖心 | 国产精品嫩穴 | 亚洲天堂日本 | 色婷婷狠狠五月综合天色拍 | 国产极品美女久久久 | av我不卡 |