It appears that TYPE_USE annotations cannot be accessed through reflection when the annotated type is a nested, generic interface.
Please observe the following example:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
public class LostAnnotation {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface SomeTypeAnnotation {
}
@SomeTypeAnnotation Map<String, String> map;
@SomeTypeAnnotation Entry<String, String> entry;
public static @SomeTypeAnnotation Entry<String, String> someMethod(
@SomeTypeAnnotation Map<String, String> map,
@SomeTypeAnnotation Entry<String, String> entry) {
return null;
}
public static void main(String[] args) throws Exception {
Class<LostAnnotation> clazz = LostAnnotation.class;
Method method = clazz.getMethod("someMethod", Map.class, Entry.class);
AnnotatedType[] types = method.getAnnotatedParameterTypes();
print("map field", clazz.getDeclaredField("map").getAnnotatedType());
print("map parameter", types[0]);
print("entry field", clazz.getDeclaredField("entry").getAnnotatedType());
print("entry parameter", types[1]);
print("entry return type", method.getAnnotatedReturnType());
}
static void print(String title, AnnotatedType type) {
System.out.printf("%s: %s%n", title, Arrays.asList(type.getAnnotations()));
}
}
The expected output of the above code is
map field: [@LostAnnotation$SomeTypeAnnotation()]
map parameter: [@LostAnnotation$SomeTypeAnnotation()]
entry field: [@LostAnnotation$SomeTypeAnnotation()]
entry parameter: [@LostAnnotation$SomeTypeAnnotation()]
entry return type: [@LostAnnotation$SomeTypeAnnotation()]
However, the actual output of the above code is
map field: [@LostAnnotation$SomeTypeAnnotation()]
map parameter: [@LostAnnotation$SomeTypeAnnotation()]
entry field: []
entry parameter: []
entry return type: []
The annotation is correctly retrieved from every usage of the Map
interface. However, on every usage of the Entry
interface, be it field, return type or parameter, the annotation is lost. The only explanation that I have for this is that the Entry
interface is nested inside the Map
interface.
I ran the above example on the newest oracle JDK (8u121) on win64. Am I doing something wrong or could this be a bug?
My Annotation is nested for readability. Making it a top-level interface doesn't change anything.