简体   繁体   中英

How to get TYPE_USE annotations on a generic bound

I have this case:

public class SomeClass<T> {
    public <@A1 S extends @A2 T> @A3 S myMethod() { ...}
}

and I'm trying to get the @A2 annotation on the bound T .
This is what I'm seeing, assuming myMethod is SomeClass.class.getDeclaredMethod("myMethod") . Type casts removed for readability.

  • myMethod.getGenericReturnType().getAnnotations() returns @A1 (as expected, I guess)
  • myMethod.getGenericReturnType().getBounds()[0].getAnnotations() returns nothing (?? shoudn't it be @A2 ??)
  • myMethod.getAnnotatedReturnType().getAnnotations() returns @A3 (as expected, I guess)
  • myMethod.getAnnotatedReturnType().getAnnotatedBounds()[0].getAnnotations() returns nothing (as excepted, I guess)

It seems like @A2 got lost... and that doesn't sound sensible. Am I doing something wrong or is this indeed some bizarre behavior?

UPDATE: It is indeed a JDK bug, which I reported and it got accepted asJDK-8191466

All type annotations can be retrieved through the AnnotatedType hierarchy, except for the TypeVariable , whose annotations can be retrieve through AnnotatedTypeVariable.getType() which will be an instance of TypeVariable which extends AnnotatedElement now and happens to be identical with the object returned by Method.getGenericReturnType() .

So you can retrieve all information, eg

AnnotatedType art = myMethod.getAnnotatedReturnType();
System.out.print(
    Arrays.toString(art.getAnnotations())+" "+art.getType().getTypeName()+" -> ");
final boolean typeVariable = art instanceof AnnotatedTypeVariable;
if (typeVariable) System.out.print('<');
System.out.print(Arrays.toString(((AnnotatedElement)art.getType()).getAnnotations()) + " ");
System.out.print(art.getType().getTypeName());
if (typeVariable) {
    AnnotatedTypeVariable atv = (AnnotatedTypeVariable)art;
    AnnotatedType[] annotatedBounds = atv.getAnnotatedBounds();
    if (annotatedBounds.length > 0) {
        System.out.print(" extends ");
        for (AnnotatedType aBound: annotatedBounds) {
            System.out.print(Arrays.toString(aBound.getAnnotations()) + " ");
            System.out.print(aBound.getType().getTypeName() + ", ");
        }
    }
    System.out.println(">");
}

will print

[@A3()] S -> <[@A1()] S extends [@A2()] T, >

When your invocation of ((AnnotatedTypeVariable)myMethod.getAnnotatedReturnType()) .getAnnotatedBounds()[0].getAnnotations() does not provide @A2 , you should recheck that A2 truly has @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) .

Of course, that's the “simplified” version handling only your specific method.

To handle all possible cases, you will need much more instanceof s, dealing with these disjunct type hierarchies of Type and AnnotatedType , especially when processing annotated parameterized types and annotated generic array types.

As said, TypeVariable is different, as it extends AnnotatedElement and also has the getAnnotatedBounds() method. So in this specific case, an alternative way to process the method is

List<TypeVariable<?>> typeParameters = Arrays.asList(myMethod.getTypeParameters());

for (TypeVariable<?> tv: typeParameters) {
    System.out.print("< "+Arrays.toString(tv.getAnnotations())+" "+tv.getName());
    AnnotatedType[] annotatedBounds = tv.getAnnotatedBounds();
    if (annotatedBounds.length > 0) {
        System.out.print(" extends ");
        for (AnnotatedType aBound: annotatedBounds) {
            System.out.print(Arrays.toString(aBound.getAnnotations()) + " ");
            System.out.print(aBound.getType().getTypeName() + ", ");
        }
    }
    System.out.print("> ");
}

AnnotatedType art = myMethod.getAnnotatedReturnType();
System.out.print(Arrays.toString(art.getAnnotations()) + " ");
int ix = typeParameters.indexOf(art.getType());
if (ix >= 0) System.out.print("[ref to type parameter #" + ix + "] ");
System.out.println(art.getType().getTypeName());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM