Java AnnotatedElement
Represents an annotated element of the program currently running in this VM.
根据注释可以看出,AnnotatedElement代表在当前运行的java虚拟机中一个可以被注解的元素。
在定义注解时,通过Target指定注解使用范围需要是枚举类ElementType。
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
同时,该接口中方法返回的所有注解都是不可变的和可序列化的。 调用方可以修改此接口的方法返回的数组,而不会影响其他调用方。
该接口定义了7个方法:
default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
判断元素是否只在指定类型annotationClass注解。
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
返回指定类型annotationClass注解,如果不存在返回null;
Annotation[] getAnnotations();
返回此元素上存在的注解。 如果此元素上没有注解,则返回值为长度为0的数组。
default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass);
返回与此元素相关的注解。 如果没有与此元素相关的注解,则返回值为长度为0的数组。
The difference between this method and getAnnotation(Class) is that this method detects if its argument is a repeatable annotation type (JLS 9.6), and if so, attempts to find one or more annotations of that type by “looking through” a container annotation.
default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
则返回该元素直接存在的注解, 此方法忽略继承的注解。
default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass);
返回此元素指定类型annotationClass直接存在或间接存在的注解,此方法将忽略继承的注解。
The difference between this method and getDeclaredAnnotation(Class) is that this method detects if its argument is a repeatable annotation type (JLS 9.6), and if so, attempts to find one or more annotations of that type by “looking through” a container annotation if one is present.
Annotation[] getDeclaredAnnotations();
返回直接存在于此元素上的注解。 此方法将忽略继承的注解。
如果此元素上没有直接存在的注解,则返回值为长度为0的数组。
四个限定词
在分析这几个方法之前我们先给定四个限定词:directly present、indrectly present、present和associated。
必须注意这四个限定词存在的前提是注解是运行时被保留的注解,也就是我们这里讨论的注解,@Retention的取值都是RetentionPolicy.RUNTIME。
这四个限定词的含义如下:
如果一个注解A是直接添加(声明)在一个元素E上面的,那么这个注解A就是directly present在这个元素上。
如果一个注解A是可重复(repetable)的,并且另外一个注解A1直接出现在元素E上,并且A1是A的包含注解类型,那么注解A就是indrectly present在元素E上。
present有两种情况:
- 注解A是directly present在元素E上。
- 元素E是一个类,并且注解A不是directly present在元素E上,并且A是可以继承(inheritable)的,并且A是present在E的父类上。
associated有两种情况:
- 注解A是directly或者indirectly present在元素E上。
- 上面的判断为false,并且E是一个类,并且注解A是可以继承(inheritable)的,并且A是associated 在E的父类上。
可以看出,Directly present是范围最小的,只能是元素上显式声明的注解,Indirectly present针对可重复注解和包含注解类型的情况,present在Directly present基础上增加了继承的情况,associated在Directly present和Indirectly的基础上增加了继承的情况。
实际上AnnotatedElement中的方法都是根据这些限定词来返回注解的,也就是说,不同的方法可能返回不同限定词指定的注解。下面我们来将方法与限定词一一对应起来。
限定词与方法的对应
下面这个表格总结了AnnotatedElement不同方法返回的注解的present情况:
方法 | Directly Present | Indirectly Present | Present | Associated |
T getAnnotation(Class<T>) | ✅ | |||
Annotation[] getAnnotations | ✅ | |||
T[] getAnnotationsByType(Class<T>) | ✅ | |||
T getDeclaredAnnotation(Class<T> annotationClass) | ✅ | |||
T[] getDeclaredAnnotationsByType(Class<T> annotationClass) | ✅ | ✅ | ||
Annotation[] getDeclaredAnnotations() | ✅ |