为什么在存在注释时 `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没有@Retentionmeta-annotation,所以只保留在class文件中。但是,它必须在运行时保留,以便通过反射访问。来自RetentionPolicy.RUNTIMEdocs

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{}