java 如何获取泛型绑定上的TYPE_USE注解

7bsow1i6  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(155)

我有这个案子:

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

我试图在绑定的T上获取@A2注解。
这就是我看到的,假设myMethodSomeClass.class.getDeclaredMethod("myMethod")。为了可读性,删除了类型转换。

  • myMethod.getGenericReturnType().getAnnotations()返回@A1(我猜和预期的一样)
  • myMethod.getGenericReturnType().getBounds()[0].getAnnotations()返回 nothing(??不应该是@A2??)
  • myMethod.getAnnotatedReturnType().getAnnotations()返回@A3(我猜和预期的一样)
  • myMethod.getAnnotatedReturnType().getAnnotatedBounds()[0].getAnnotations()返回 nothing(我猜是例外)

好像是@A2迷路了……这听起来不太明智是我做错了什么,还是这确实是一些奇怪的行为?
更新:这确实是一个JDK错误,我报告了它,它被接受为JDK-8191466

bvhaajcl

bvhaajcl1#

所有类型的注解都可以通过AnnotatedType层次结构检索,除了TypeVariable,它的注解可以通过AnnotatedTypeVariable.getType()检索,AnnotatedTypeVariable.getType()将是TypeVariable的一个示例,它现在扩展了AnnotatedElement,碰巧与Method.getGenericReturnType()返回的对象相同。
因此,您可以检索所有信息,例如:

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(">");
}

将打印

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

如果调用((AnnotatedTypeVariable)myMethod.getAnnotatedReturnType()) .getAnnotatedBounds()[0].getAnnotations()时没有提供@A2,则应该重新检查A2是否确实具有@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE)
当然,这是“简化”版本,只处理您的特定方法。
为了处理所有可能的情况,您将需要更多的instanceof,处理TypeAnnotatedType的这些析取类型层次结构,特别是在处理带注解的参数化类型和带注解的泛型数组类型时。
正如所说,TypeVariable是不同的,因为它扩展了AnnotatedElement,并且还具有getAnnotatedBounds()方法。所以在这个特定的例子中,处理方法的另一种方法是

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());

相关问题