
- 前言
- 1 自定义注解 NotNull
- 2 使用接口实现 NotNull注解的功能
- 3 测试效果
- 4 控制台的异常栈信息
关于参数校验,一直是个困扰人的事。这次使用注解+反射,实现自己的非空校验。
1 自定义注解 NotNullpackage com.example;
import java.lang.annotation.*;
/**
* 注解非空,用于校验实例变量不能为空。实现逻辑在 Check接口中。
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NotNull {
/**
* 错误信息描述
*/
String errorMsg();
}
2 使用接口实现 NotNull注解的功能
package com.example;
import java.lang.reflect.Field;
/**
* 所有要校验的类,实现这个接口
*/
public interface Check {
/**
* 校验参数
*/
default void doCheck() {
final Field[] declaredFields = this.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
// 当前变量是这个 Check 接口的实现类、或有NotNull注解
if (Check.class.isAssignableFrom(declaredField.getType()) || declaredField.isAnnotationPresent(NotNull.class)) {
declaredField.setAccessible(true);
deepCheck(declaredField);
}
}
}
private void deepCheck(Field declaredField) {
try {
final Object declaredFieldValue = declaredField.get(this);
if (declaredFieldValue instanceof Check) {
((Check) declaredFieldValue).doCheck();
return;
}
if (declaredFieldValue == null && declaredField.isAnnotationPresent(NotNull.class)) {
final NotNull notNull = declaredField.getAnnotation(NotNull.class);
final String errorMsg = notNull.errorMsg();
throw new IllegalArgumentException(errorMsg);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
3 测试效果
package com.example;
public class MainClient implements Check {
@NotNull(errorMsg = "check2不能为空")
private Check2 check2;
@NotNull(errorMsg = "aaa")
private String aaa;
public static void main(String[] args) {
MainClient client = new MainClient();
client.check2 = new Check2();
client.doCheck();
}
}
class Check2 implements Check {
@NotNull(errorMsg = "aaa不能为空")
private String aaa="";
}
4 控制台的异常栈信息
Exception in thread "main" java.lang.IllegalArgumentException: aaa
at com.example.Check.deepCheck(Check.java:31)
at com.example.Check.doCheck(Check.java:16)
at com.example.MainClient.main(MainClient.java:14)
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)