本文介绍了如何在通用边界上获取 TYPE_USE 注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个案例:

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

我正在尝试在绑定的 T 上获取 @A2 注释.
这就是我所看到的,假设 myMethodSomeClass.class.getDeclaredMethod("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() 返回 @A1(正如预期的那样)
  • myMethod.getGenericReturnType().getBounds()[0].getAnnotations() 返回 nothing (?? 不应该是 @A2代码> ??)
  • myMethod.getAnnotatedReturnType().getAnnotations() 返回 @A3(正如预期的那样,我猜)
  • myMethod.getAnnotatedReturnType().getAnnotatedBounds()[0].getAnnotations() 返回什么都没有(我猜是例外)
  • 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)

似乎 @A2 迷路了……这听起来不明智.是我做错了什么还是这确实是一些奇怪的行为?

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

更新:这确实是一个 JDK 错误,我报告了它并被接受为 JDK-8191466

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

推荐答案

所有类型注解都可以通过 AnnotatedType 层次结构检索,除了 TypeVariable,其注解可以通过 AnnotatedTypeVariable.getType() 检索,这将是 TypeVariable 的一个实例,它现在扩展了 AnnotatedElement 并且恰好与返回的对象相同Method.getGenericReturnType().

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, e.g.

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).

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.

要处理所有可能的情况,您将需要更多 instanceof 来处理 TypeAnnotatedType 的这些分离类型层次结构,尤其是处理带注释的参数化类型和带注释的泛型数组类型时.

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

如前所述,TypeVariable 是不同的,因为它扩展了 AnnotatedElement 并且还有 getAnnotatedBounds() 方法.因此,在这种特定情况下,处理该方法的另一种方法是

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

这篇关于如何在通用边界上获取 TYPE_USE 注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 20:08