问题描述
我有这种情况:
public class SomeClass<T> {
public <@A1 S extends @A2 T> @A3 S myMethod() { ...}
}
并且我正在尝试在绑定的T
上获取@A2
批注.
假设myMethod
是SomeClass.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()
不返回 (不是@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
推荐答案
除TypeVariable
之外,所有类型的注释都可以通过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
来处理Type
和AnnotatedType
的这些离散类型层次结构,尤其是在处理带注释的参数化类型和带注释的泛型数组类型时.
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.
如上所述,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批注的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!