这段代码会抛出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()); } }
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/17435099.html