问题描述
我有这个案例:
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()
返回 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
来处理 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 注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!