Java中的注解 – @NotNull「建议收藏」

Java中的注解 – @NotNull「建议收藏」比如说,你写了一个后台系统,接收用户的请求,经过运算后返回结果,很通用的一个实现方案。假定所有的方法都需要校验参数是否为空,不然就可能有NullPointerException,如果系统有N个接口,每个接口参数有M个,你需要写N*M个if判断语句。如if(StringUtils.isBlank(request.getA())){thrownewIllegalArgume…

大家好,又见面了,我是你们的朋友全栈君。

比如说,你写了一个后台系统,接收用户的请求,经过运算后返回结果,很通用的一个实现方案。假定所有的方法都需要校验参数是否为空,不然就可能有NullPointerException,如果系统有N个接口,每个接口参数有M个,你需要写N * M个if判断语句。如

if (StringUtils.isBlank(request.getA())) {
    throw new IllegalArgumentException("A is blank");
}

这么写下来,肯定代码是很丑的。那怎么办呢?记得我们之前说过的编码理念,Don’t repeat yourself,就派上用场了。

Java中已经定义了@NotNull的注解,可以用来做这件事。(我们也可以自定义注解,见上一篇文章)在我们这个场景,我们的需求是:

  1. 在请求类中,所有不能为空的属性上,需要标记为@NotNull
  2. 写一个通用的validation方法,获取请求中的参数,检查如果有标记@NotNull,且参数的值为null,则抛出异常。

代码实现,

public class QueryUserRequest extends BaseRequest {
    @NotNull
    private String name;
    @NotNull
    private Integer age;
    private Boolean gender;
    // 省略getter, setter方法
}

为了使校验参数的方法得到最大的通用性,我们把它放到BaseRequest中,让所有的request都继承这个父类。

public class BaseRequest {
    public void nullFieldValidate() throws IllegalAccessException, InvocationTargetException {
        Field[] fields = this.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            Object fieldValue = runGetter(field, this);

            boolean isAnnotationNotNull = field.isAnnotationPresent(NotNull.class);
            if (isAnnotationNotNull && fieldValue == null) {
                System.out.println(fieldName + " can't be null");
            }
        }
    }

    // 由于所有子类的属性都是private的,所以必须要找到属性的getter方法
    //  以下代码借鉴[stackoverflow的文章](https://stackoverflow.com/questions/13400075/reflection-generic-get-field-value)
    public Object runGetter(Field field, Object instance) {
        // MZ: Find the correct method
        for (Method method : instance.getClass().getDeclaredMethods()) {
            if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3))) {
                if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase())) {
                    // MZ: Method found, run it
                    try {
                        return method.invoke(instance);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        System.out.println("Could not determine method: " + method.getName());
                    }
                }
            }
        }
        return null;
    }
}

对于获取类属性上的注解有3种方法,如果有其他的方法也可以告知

Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
    // 方法1
    Annotation[] annotations = field.getDeclaredAnnotations();
    for (Annotation annotation : annotations) {
        if (annotation instanceof NotNull && fieldValue == null) {
            System.out.println(field.getName() + " can't be null");
        }
    }
    // 方法2
    Annotation annotation = field.getAnnotation(NotNull.class);
    if (annotation != null && fieldValue == null) {
            System.out.println(field.getName() + " can't be null");
    }
    // 方法3
    boolean isAnnotationNotNull = field.isAnnotationPresent(NotNull.class);
    if (isAnnotationNotNull && fieldValue == null) {
            System.out.println(field.getName() + " can't be null");
    }
}

作者:rockops
链接:https://www.jianshu.com/p/a997d03d0cd6

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138674.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 深度学习之softmax损失函数[通俗易懂]

    深度学习之softmax损失函数[通俗易懂]深度学习之softmax损失函数归一化向量的每个元素均大于0小于1,且和为1,所以可以将其看作归属各个类别的概率。损失函数可以看作真实类别的负对数概率,希望其越小。importnumpyasnpD=784K=10N=128#scores是分值矩阵,每行代表一个样本scores=np.random.randn(N,K)print(scores.shape)#样本标签y=np.random.randint(K,size=N)print(y.shape)#指数化分值矩

    2022年6月26日
    32
  • Linux常用命令大全(非常全!!!)

    Linux常用命令大全(非常全!!!)Linux常用命令大全(非常全!!!)最近都在和Linux打交道,感觉还不错。我觉得Linux相比windows比较麻烦的就是很多东西都要用命令来控制,当然,这也是很多人喜欢linux的原因,比较短小但却功能强大。我将我了解到的命令列举一下,仅供大家参考:系统信息arch显示机器的处理器架构uname-m显示机器的处理器架构uname-r显示正在使用的内核版本d…

    2022年4月27日
    31
  • 图书销售管理系统设计与实现「建议收藏」

    图书销售管理系统设计与实现「建议收藏」图书销售管理系统设计与实现             图书销售管理系统设计与实现本系统带程序说明书 有需要源码虚学习交流的可以去我上传的资源里面找,找不到的话,评论我,或者站内私信留下邮箱,我给你发,也可以联系我ID。因为最近太忙一直没有上传完。emmmm 跟着现代社会的开展越来越多的公司、企业、出售集体等现已不满意于仅仅只是静态网页技能介绍公司背景环境以及开展方向,愈加…

    2022年6月10日
    28
  • android scaleanimation动画,Android 的ScaleAnimation 缩放动画基本运用

    android scaleanimation动画,Android 的ScaleAnimation 缩放动画基本运用因为今天用到了ScaleAnimation缩放动画就写一下,加深一下印象。用ScaleAnimation有几个重载方法,这里就将八个参数的重载方法。ScaleAnimation(floatfromX,floattoX,floatfromY,floattoY,intpivotXType,floatpivotXValue,intpivotYType,floatpivotYV…

    2022年10月16日
    0
  • signature=0fdde99449705347b1bc3148e0519684,yarn.lock · mirrors_yeoman/generator-generator – Gitee.co…

    signature=0fdde99449705347b1bc3148e0519684,yarn.lock · mirrors_yeoman/generator-generator – Gitee.co…#THISISANAUTOGENERATEDFILE.DONOTEDITTHISFILEDIRECTLY.#yarnlockfilev1″@babel/code-frame@^7.0.0″,”@babel/code-frame@^7.0.0-beta.35″:version”7.5.5″resolved”https://registry.yarnpkg.com/@…

    2022年9月3日
    3
  • Springboot框架是什么_javaweb框架主要的三大基本框架

    Springboot框架是什么_javaweb框架主要的三大基本框架对于spring框架,我们接触得比较多的应该是springmvc、和spring。而spring的核心在于IOC(控制反转)和DI(依赖注入)。而这些框架在使用的过程中会需要配置大量的xml,或者需要做很多繁琐的配置。springboot框架是为了能够帮助使用spring框架的开发者快速高效的构建一个基于spirng框架以及spring生态体系的应用解决方案。它是对“约定优于配置”这个理念下的一个最佳实践。因此它是一个服务于框架的框架,服务的范围是简化配置文件。…

    2022年8月20日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号