如何捕获通用 super class 类型参数的注释?

How to capture annotations on generic super class type arguments?

使用 java 8 可以创建带有目标 ElementType.TYPE_USE 的注释。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE})
public @interface MyAnnotation {
}

此注释可应用于传递给通用超类的类型 class,例如:

public class ClassA extends BaseClass<@MyAnnotation ClassB,@MyAnnotation ClassC>{
...
}

使用下面的代码,我可以轻松地从 ClassA 的实例动态检索超级 class BaseClass 的类型参数列表。

ClassA instanceOfA = new ClassA();
...
Class classOfA = instanceOfA.getClass();
ParameterizedType type =  (ParameterizedType)classOfA.getGenericSuperclass();
Type[] types = type.getActualTypeArguments();

// types[0] --> ClassB
// types[1] --> ClassC

从那里,我试图找到一种方法来检索每个类型参数的注释,但没有成功。

有没有办法动态地(运行时)检索这些注释?谢谢

编辑: 额外的精度,我想支持以下用例:

public class ClassA extends BaseClass<@Annotation1 ClassB,@Annotation2 ClassC>{
...
}

public class ClassD extends BaseClass<@Annotation3 ClassB,@Annotation4 ClassC>{
...
}

在此示例中,ClassB 在 ClassA 或 ClassD 的上下文中的注释不同(对于 ClassC 也是如此)。

棘手:

 import java.lang.reflect.*;

 AnnotatedType baseClassAt = classOfA.getAnnotatedSuperclass();
 assert (at instanceof AnnotatedParameterizedType);

 AnnotatedType[] aTypes = ((AnnotatedParameterizedType)baseClassAt)
     .getAnnotatedActualTypeArguments();
 assert aTypes.length == 2;

 MyAnnotation myAnno0 = aTypes[0].getAnnotation(MyAnnotation.class);
 MyAnnotation myAnno1 = aTypes[1].getAnnotation(MyAnnotation.class);

对于 class 级别的注释,我们可以对每个 class 对象使用 getAnnotations() 方法。在您的代码中,我们需要将 Type 类型转换为 Class 并为其获取注释。

例如:

Class classOfA = instanceOfA.getClass();
ParameterizedType type =  (ParameterizedType)classOfA.getGenericSuperclass();
Type[] types = type.getActualTypeArguments();

for(Type t: types){
    System.out.println(t.getTypeName());

    Annotation[] ans = ((Class) t).getAnnotations();
    for(Annotation an: ans){
        System.out.println(an.annotationType());
    }
}

下面是一个完整的例子,有两个不同的注释来突出区别:

import java.lang.annotation.*;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class AnnotationChecker {

    public static void main(String[] args) {
        ClassA instanceOfA = new ClassA();

        Class classOfA = instanceOfA.getClass();
        ParameterizedType type =  (ParameterizedType)classOfA.getGenericSuperclass();
        Type[] types = type.getActualTypeArguments();

        for(Type t: types){
            System.out.println(t.getTypeName());

            Annotation[] ans = ((Class) t).getAnnotations();
            for(Annotation an: ans){
                System.out.println(an.annotationType());
            }
        }

    }

}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation1 {

}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation2 {

}


class ClassA extends BaseClass<ClassB,ClassC>{

}

class BaseClass<ClassB, ClassC> {

}

@MyAnnotation1
class ClassB {

}

@MyAnnotation2
class ClassC {

}