The Javadocs entry for getDeclaredAnnotations
say the following:
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.
So, I expect this function to return an array of length 1 on doSometing
, yet, it returns an array of length 0. Why? getAnnotation
for the relevant type also 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{} }
Actual MCVE output:
main: doSomething: wait: wait: wait: equals: toString: hashCode: - jdk.internal.HotSpotIntrinsicCandidate getClass: - jdk.internal.HotSpotIntrinsicCandidate notify: - jdk.internal.HotSpotIntrinsicCandidate notifyAll: - jdk.internal.HotSpotIntrinsicCandidate
Expected MCVE output:
// irrelevant method entries aren't shown doSomething: - AnnotationTest.ExampleAnnotation // irrelevant method entries aren't shown
Advertisement
Answer
According to the Java Language Specification ยง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
.
Your ExampleAnnotation
does not have a @Retention
meta-annotation, so it is only retained in the class file. However, it must be retained at runtime in order to be accessed with reflection. From the docs of RetentionPolicy.RUNTIME
:
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.
Compare that with the description for CLASS
:
Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.
So to get your desired output, you should declare your ExampleAnnotation
like this:
@Retention(RetentionPolicy.RUNTIME) @interface ExampleAnnotation{}