注解与反射接口AnnotatedElement

发布时间:2024年01月08日

定义注解后,如何获取注解中的内容呢?反射包java.lang.reflect下的AnnotatedElement接口提供这些方法。这里注意:只有注解被定义为RUNTIME后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

AnnotatedElement 中需要了解的API

AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的方法来访问Annotation信息。

AnnotatedElement 接口API 如下

  • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
    判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false

  • T getAnnotation(Class annotationClass)
    返回该程序元素上存在的、指定类型的注解。如果没有则返回null。

  • Annotation[] getAnnotations()
    返回该程序元素上存在的所有注解。如果没有则返回空数组[]。

  • T[] getAnnotationsByType(Class annotationClass)
    返回该程序元素上存在的、指定类型的注解数组。如果没有则返回空数组[]。getAnnotationsByType方法与 getAnnotation的区别在于,getAnnotationsByType 会检测封装在注解容器的注解

  • T getDeclaredAnnotation(Class annotationClass)
    返回直接存在于此元素上的所有注解(会忽略继承的注解)。如果没有则返回null。

  • Annotation[] getDeclaredAnnotations()
    返回直接存在于此元素上的所有注解及注解对应的重复注解容器(会忽略继承的注解。如果没有则返回空数组[]。

  • T[] getDeclaredAnnotationsByType(Class annotationClass)
    返回直接存在于此元素上的所有注解(会忽略继承的注解,会检测封装在注解容器的注解)。如果没有则返回空数组[]。

测试案例如下:

准备 User 注解类(可重复使用)

package com.gump.annotation.repeatable;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Users.class)//可使用重复注解
public @interface User {
    String value();
}

准备 Users 注解类(容器注解)

package com.gump.annotation.repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Users {
    User[] value();
}

准备 Country 注解类(可继承)

package com.gump.annotation.repeatable;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Inherited//子类可继承
public @interface Country {
    String value();
}

准备 MyClass 子类

package com.gump.annotation.repeatable;
@User("you")
@User("me")
public class MyClass extends ParentClass {
    //...
}

准备 ParentClass 父类

package com.gump.annotation.repeatable;
@Country("China")
public class ParentClass {
}

准备 测试类,开始验证测试(着重理解方法之间的对比区别):

package com.gump.annotation.repeatable;
import java.lang.annotation.Annotation;
public class MyTest {
    public static void main(String[] args) {
        Class<MyClass> clazz = MyClass.class;
        boolean isUsers = clazz.isAnnotationPresent(Users.class);//true
        boolean isUser = clazz.isAnnotationPresent(User.class);//false,不会检测封装在注解容器的注解User
        boolean isCountry = clazz.isAnnotationPresent(Country.class);//true

        Users users = clazz.getAnnotation(Users.class);
        User user = clazz.getAnnotation(User.class);//null,会检测封装在注解容器的注解
        Country country = clazz.getAnnotation(Country.class);

        Annotation[] annotations = clazz.getAnnotations();//Users、Country,不会检测封装在注解容器的注解User
        Users[] annotationsByType1 = clazz.getAnnotationsByType(Users.class);
        User[] annotationsByType2 = clazz.getAnnotationsByType(User.class);//会检测封装在注解容器的注解User
        Country[] annotationsByType3 = clazz.getAnnotationsByType(Country.class);

        Users declaredAnnotation1 = clazz.getDeclaredAnnotation(Users.class);
        User declaredAnnotation2 = clazz.getDeclaredAnnotation(User.class);//null,不会检测封装在注解容器的注解User
        Country declaredAnnotation3 = clazz.getDeclaredAnnotation(Country.class);//null,忽略继承

        Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations();//Users,忽略继承Country,不会检测封装在注解容器的注解User
        Users[] declaredAnnotationsByType1 = clazz.getDeclaredAnnotationsByType(Users.class);
        User[] declaredAnnotationsByType2 = clazz.getDeclaredAnnotationsByType(User.class);//会检测封装在注解容器的注解User
        Country[] declaredAnnotationsByType3 = clazz.getDeclaredAnnotationsByType(Country.class);//返回[],忽略继承

    }
}

测试对比小结:

  • 包含 Declared 的方法会忽略继承的注解;
  • 包含 ByType 的方法会检测封装在注解容器的注解;
文章来源:https://blog.csdn.net/glb168/article/details/135462675
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。