這段代碼會拋出NPE,你造嗎?----封裝AssertUtil來友好地利用斷言

運行下面代碼,會拋出NPE。你知道爲什麼嗎?

import cn.hutool.core.lang.Assert;

public class TestMain {

    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        Assert.isTrue(myClass.myProperty == 0);
    }


    private static class MyClass {
        private Integer myProperty;

    }
}

原因:初始化myClass對象後,Integer類型的myProperty屬性的值是默認值null。此時,執行myClass.myProperty == 0,其實是調用了 Integer#intValue()方法進行拆箱操作,由於Integer對象是null,致使NPE。

上面代碼在IDE裏不會提示任何問題。而下面代碼,IDE則會給出NPE提示。

 

 

我今天在寫一個對外暴露的接口方法,利用斷言判斷入參合法性時,恰好想到了這個問題點。就像上面的示例代碼,還沒到執行斷言呢,就拋出了NPE了。顯然,要先斷言屬性不爲null。

如下是我改完後的程序代碼

    public Result<UserSignDTO> userHasSign(UserSignQuery userSignQuery) {
        try {
            Assert.notNull(userSignQuery);
            Assert.notNull(userSignQuery.getIdcardNo());
            Assert.notNull(userSignQuery.getEnterpriseId());
            Assert.notNull(userSignQuery.getProviderId());
            Assert.isTrue(userSignQuery.getEnterpriseId()>0);
            Assert.isTrue(userSignQuery.getProviderId()>0);
            
            ...
            
        } catch (IllegalArgumentException e) {
            return Result.err(e.getMessage());
        }
    }

 

毋庸置疑,用斷言可以增加代碼的優雅度。而這一坨Assert,卻跟優雅沾不上邊。

 

於是乎,發揮點匠心精神吧。下面AssertUtil問世,基於Assert進行工具的封裝。

package com.emax.common.util;

import cn.hutool.core.lang.Assert;

public class AssertUtil {
    /**
     * 斷言所有對象是否不爲{@code null} ,如果爲{@code null} 拋出{@link IllegalArgumentException} 異常
     *
     * @param errMsg 斷言失敗的錯誤消息
     * @param objects
     */
    @SafeVarargs
    public static <T> void allNotNull(String errMsg, T... objects) throws IllegalArgumentException {
        for (T object : objects) {
            T t = errMsg == null ? Assert.notNull(object) : Assert.notNull(object, errMsg);
        }
    }

    /**
     * 斷言所有對象是否不爲{@code null} ,如果爲{@code null} 拋出{@link IllegalArgumentException} 異常
     *
     * @param objects
     */
    public static <T> void allNotNull(T... objects) throws IllegalArgumentException {
        allNotNull(null, objects);
    }

    /**
     * 判斷對象是數字,並且大於0
     *
     * @param number
     * @throws IllegalArgumentException
     */
    public static void gt0(Number number) throws IllegalArgumentException {
        Assert.notNull(number);
        Assert.isTrue(number.longValue() > 0);
    }
    
    ....其他斷言方法
    
}

 

OK,改爲使用AssertUtil斷言,如下,是不是優雅?你品。

    public Result<UserSignDTO> userHasSign(UserSignQuery userSignQuery) {
        try {
            AssertUtil.allNotNull(userSignQuery, userSignQuery.getIdCardNo());
            AssertUtil.gt0(userSignQuery.getEnterpriseId());
            AssertUtil.gt0(userSignQuery.getProviderId());
            if (userSignQuery.getUserId() == 0 || StringUtils.isBlank(userSignQuery.getIdcardNo())) {
                throw new IllegalArgumentException("userId或身份證號碼必傳一項");
            }
            
            ...
            
        } catch (IllegalArgumentException e) {
            return Result.err(e.getMessage());
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章