當前位置:首頁 > 公眾號精選 > 程序員小灰
[導(dǎo)讀]對于Java程序員來說,null是令人頭痛的東西。時常會受到空指針異常(NPE)的騷擾。連Java的發(fā)明者都承認這是他的一項巨大失誤。那么,有什么辦法可以避免在代碼中寫大量的判空語句呢?有人說可以使用JDK8提供的Optional來避免判空,但用起來還是有些麻煩。作者在日常工作中封裝了一個工具,可以鏈式調(diào)用對象成員而無需判空,相比原有的if null邏輯和JDK8提供的Optional更加優(yōu)雅易用。

△Hollis, 一個對Coding有著獨特追求的人△ 這是Hollis的第 307 篇原創(chuàng)分享 作者 l  上帝愛吃蘋果 來源 l Hollis(ID:hollischuang)

對于Java程序員來說,null是令人頭痛的東西。時常會受到空指針異常(NPE)的騷擾。連Java的發(fā)明者都承認這是他的一項巨大失誤。 那么,有什么辦法可以避免在代碼中寫大量的判空語句呢? 有人說可以使用 JDK8提供的 Optional 來避免判空,但是用起來還是有些麻煩。 作者在日常工作中,封裝了一個工具,可以可以鏈式調(diào)用對象成員而無需判空,相比原有的if null邏輯 和 JDK8提供的 Optional 更加優(yōu)雅易用,在工程實踐中大大提高了編碼效率,也讓代碼更加的精準和優(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進行判空,雖然有些麻煩,到也能用,通過 JDK8 提供的 Optional 工具也是可以,但還是有些麻煩。 而下文的 OptionalBean 提供一種可以鏈式不斷地調(diào)用成員變量而無需判空的方法,直接鏈式調(diào)用到你想要獲取的目標變量,而無需擔心空指針的問題。

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

OptionalBean 工具

/**

@author Axin

@since 2020-09-10

@summary 鏈式調(diào)用 bean 中 value 的方法

*/


public final class OptionalBean<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 <T>

     * @return

     */


    public static <T> OptionalBean<T> of(T value) {

        return new OptionalBean<>(value);

    }

    /**

     * 包裝一個可能為空的 bean

     * @param value

     * @param <T>

     * @return

     */


    public static <T> OptionalBean<T> ofNullable(T value) {

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

    }

    /**

     * 取出具體的值

     * @param fn

     * @param <R>

     * @return

     */


    public T get() {

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

    }

    /**

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

     * @param fn

     * @param <R>

     * @return

     */


    public <R> OptionalBean<R> getBean(Function<? super 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<? extends T> other) {

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

    }

    /**

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

     * @param exceptionSupplier

     * @param <X>

     * @return

     * @throws X

     */


    public <X extends Throwable> orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {

        if (value != null) {

            return value;

        } else {

            throw exceptionSupplier.get();

        }

    }

    public boolean isPresent() {

        return value != null;

    }

    public void ifPresent(Consumer<? super T> consumer) {

        if (value != null)

            consumer.accept(value);

    }

    @Override

    public int hashCode() {

        return Objects.hashCode(value);

    }

    /**

     * 空值常量

     * @param <T>

     * @return

     */


    public static<T> OptionalBean<T> empty() {

        @SuppressWarnings("unchecked")

        OptionalBean<T> none = (OptionalBean<T>) EMPTY;

        return none;

    }

}

工具設(shè)計主要參考了 Optional 的實現(xiàn),再加上對鏈式調(diào)用的擴展就是上述的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. 基本調(diào)用

    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一下:

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


      

—————END—————



喜歡本文的朋友,歡迎關(guān)注公眾號 程序員小灰,收看更多精彩內(nèi)容

                     
點個[在看],是對小灰最大的支持!

免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉