首页 > 其他分享 >自定义注解+反射机制

自定义注解+反射机制

时间:2023-02-24 09:55:39浏览次数:40  
标签:反射 Target 自定义 field Length 注解 ElementType class

@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;
}
}
  1. Class.getDeclaredFields();
    返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。
  2. field.isAnnotationPresent,这个方法实际上是让Length注解继承了Annotation类,查看filed字段是否带有Length注解
  3. field.getAnnotation,获取这个字段上所有的注解信息。
  4. field.setAcessible,将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查;实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问 ;

    由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的。

  5. 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

相关文章

  • 反射
    多态是不能调用子类独有的方法的,形象来说程序是不知道user是个child如果能在运行过程中知道user是什么类型,那就能用child里面的方法了好比通过照镜子知道自己长什么样,ja......
  • 声明式事务操作-完全注解方式
    1.创建配置类packagespring.config;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.context.annotation.Bean;importorg.springframe......
  • reflect反射结构体
    packagemainimport( "fmt" "reflect")typeUnivercitystruct{ Namestring Ageint}func(uUnivercity)Sport(){ fmt.Println("学校开展运动会")}......
  • Java 反射
    1.小demo快速上手读取配置文件信息,实现调用方法@SuppressWarnings({"all"})//取消显示指定的编译器警告publicclassReflectionQuestion{publicstaticv......
  • 三、MybatisPlus常用注解
    @TableName经过以上的测试,在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表。由此得出......
  • Java ”框架 = 注解 + 反射 + 设计模式“ 之 反射详解
    Java”框架=注解+反射+设计模式“之反射详解每博一文案无论幸福还是苦难,无论光荣还是屈辱,你都要自己遭遇与承受。——————《......
  • Nginx生成自定义证书
    1、创建存放证书的目录,此目录可自定义cd/usr/local/nginx/conf/cretmkdirkeycdkey先安装依赖包yum-yinstallporc-develzlib-develpopt-developenssl-developen......
  • 自定义属性访问
    什么是属性?下面的例子a和b是属性吗?不是,他们是全局变量,属性(attribute)是类中的成员变量,也可以理解为属性就是类变量。pythona=11234b='python'PYTHON复制全屏类中......
  • Vue3自定义指令
    Vue3自定义指令自定义指令的定义:自定义指令是用来操作DOM的,尽管vue推崇数据驱动视图的理念,但并非所有情况都适合数据驱动。自定义指令就是一种有效的补充和拓展,不仅仅......
  • fusion app自定义事件源码介绍(下)
    安装apk安装APK(filePath)lua源码function安装APK(filePath)localintent=Intent(Intent.ACTION_VIEW);intent.addCategory("android.intent.category.DEFAU......