@Target用来表示注解作用范围,超过这个作用范围,编译的时候就会报错。
@Target:注解的作用目标
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包,用于记录java文件的package信息
@Retention
source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码。
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Length { int min(); int max(); String errorMsg(); }
定义了一个可用于字段上的注解@Length。
@Data public class Student implements Serializable { private String name; @Length(min = 0,max = 100,errorMsg = "除非你升仙") private Integer age; private Integer score; @Override public String toString() { return "Student:" + '\n' + "name = " + this.name + '\n' + "age = " + this.age + '\n' + "score = " + this.score + '\n' ; } }
定义了一个学生类,把@Length用在age上。
public class Demo01 {
public static String validate(Object object) throws IllegalAccessException {
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Length.class)) {
Length length = field.getAnnotation(Length.class);
field.setAccessible(true);
Object vObject = field.get(object);
int value = ((Integer) vObject).intValue();
// int value = ((String) field.get(object)).length();
if (value < length.min() || value > length.max()) {
return length.errorMsg();
}
}
}
return null;
}
}
- Class.getDeclaredFields();
返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。 - field.isAnnotationPresent,这个方法实际上是让Length注解继承了Annotation类,查看filed字段是否带有Length注解
- field.getAnnotation,获取这个字段上所有的注解信息。
-
field.setAcessible,将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查;实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;
由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的。
- field.get,获取field上的对象。
public class Demo23 { public static void main(String[] args) { Student student = new Student(); student.setAge(200); try { ; System.out.println(Demo01.validate(student)); } catch (Exception e) { e.printStackTrace(); } } }
打印输入结果为:
标签:反射,Target,自定义,field,Length,注解,ElementType,class From: https://www.cnblogs.com/shishenapr/p/17150262.html