为什么在存在注释时 `getDeclaredAnnotations()` 返回一个空列表?
Why is `getDeclaredAnnotations()` returning an empty list when an annotation is present?
Javadocs entry for getDeclaredAnnotations
说如下:
Returns annotations that are directly present on this element. This method ignores inherited annotations. If there are no annotations directly present on this element, the return value is an array of length 0. The caller of this method is free to modify the returned array; it will have no effect on the arrays returned to other callers.
所以,我希望这个函数在 doSometing
上 return 一个长度为 1 的数组,然而,它 return 是一个长度为 0 的数组。为什么? getAnnotation
相关类型也 returns null
.
MCVE:
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class AnnotationTest{
public static void main(String[] args){
Class<?> clazz = AnnotationTest.class;
for(Method method : clazz.getMethods()){
System.out.println(method.getName() + ":");
for(Annotation annotation : method.getDeclaredAnnotations()){
System.out.println(" - " + annotation.annotationType().getName());
}
System.out.println();
}
}
@ExampleAnnotation
public void doSomething(){}
public @interface ExampleAnnotation{}
}
实际 MCVE 输出:
main:
doSomething:
wait:
wait:
wait:
equals:
toString:
hashCode:
- jdk.internal.HotSpotIntrinsicCandidate
getClass:
- jdk.internal.HotSpotIntrinsicCandidate
notify:
- jdk.internal.HotSpotIntrinsicCandidate
notifyAll:
- jdk.internal.HotSpotIntrinsicCandidate
预期 MCVE 输出:
// irrelevant method entries aren't shown
doSomething:
- AnnotationTest.ExampleAnnotation
// irrelevant method entries aren't shown
根据 Java 语言规范 §9.6.4.2,
If T
does not have a (meta-)annotation m
that corresponds to java.lang.annotation.Retention
, then a Java compiler must treat T
as if it does have such a meta-annotation m
with an element whose value is java.lang.annotation.RetentionPolicy.CLASS
.
你的ExampleAnnotation
没有@Retention
meta-annotation,所以只保留在class文件中。但是,它必须在运行时保留,以便通过反射访问。来自RetentionPolicy.RUNTIME
的docs:
Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
将其与 CLASS
的描述进行比较:
Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.
所以为了获得你想要的输出,你应该像这样声明你的ExampleAnnotation
:
@Retention(RetentionPolicy.RUNTIME)
@interface ExampleAnnotation{}
Javadocs entry for getDeclaredAnnotations
说如下:
Returns annotations that are directly present on this element. This method ignores inherited annotations. If there are no annotations directly present on this element, the return value is an array of length 0. The caller of this method is free to modify the returned array; it will have no effect on the arrays returned to other callers.
所以,我希望这个函数在 doSometing
上 return 一个长度为 1 的数组,然而,它 return 是一个长度为 0 的数组。为什么? getAnnotation
相关类型也 returns null
.
MCVE:
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class AnnotationTest{
public static void main(String[] args){
Class<?> clazz = AnnotationTest.class;
for(Method method : clazz.getMethods()){
System.out.println(method.getName() + ":");
for(Annotation annotation : method.getDeclaredAnnotations()){
System.out.println(" - " + annotation.annotationType().getName());
}
System.out.println();
}
}
@ExampleAnnotation
public void doSomething(){}
public @interface ExampleAnnotation{}
}
实际 MCVE 输出:
main:
doSomething:
wait:
wait:
wait:
equals:
toString:
hashCode:
- jdk.internal.HotSpotIntrinsicCandidate
getClass:
- jdk.internal.HotSpotIntrinsicCandidate
notify:
- jdk.internal.HotSpotIntrinsicCandidate
notifyAll:
- jdk.internal.HotSpotIntrinsicCandidate
预期 MCVE 输出:
// irrelevant method entries aren't shown
doSomething:
- AnnotationTest.ExampleAnnotation
// irrelevant method entries aren't shown
根据 Java 语言规范 §9.6.4.2,
If
T
does not have a (meta-)annotationm
that corresponds tojava.lang.annotation.Retention
, then a Java compiler must treatT
as if it does have such a meta-annotationm
with an element whose value isjava.lang.annotation.RetentionPolicy.CLASS
.
你的ExampleAnnotation
没有@Retention
meta-annotation,所以只保留在class文件中。但是,它必须在运行时保留,以便通过反射访问。来自RetentionPolicy.RUNTIME
的docs:
Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
将其与 CLASS
的描述进行比较:
Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.
所以为了获得你想要的输出,你应该像这样声明你的ExampleAnnotation
:
@Retention(RetentionPolicy.RUNTIME)
@interface ExampleAnnotation{}