定义注解后,如何获取注解中的内容呢?反射包java.lang.reflect下的AnnotatedElement接口提供这些方法。这里注意:只有注解被定义为RUNTIME后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。
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);//返回[],忽略继承
}
}
测试对比小结: