如何在泛型边界上获取TYPE_USE注释

时间:2017-11-08 09:09:20

标签: java generics reflection java-8 annotations

我有这个案子:

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

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

  • myMethod.getGenericReturnType().getAnnotations()返回@A1(正如我所料,我猜)
  • myMethod.getGenericReturnType().getBounds()[0].getAnnotations()返回没有(?? shoudn&#39;它是@A2 ??)
  • myMethod.getAnnotatedReturnType().getAnnotations()返回@A3(正如我所料,我猜)
  • myMethod.getAnnotatedReturnType().getAnnotatedBounds()[0].getAnnotations()返回没有(例如,我猜)

似乎@A2迷失了......这听起来并不合理。我做错了什么,或者这确实是一些奇怪的行为?

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

1 个答案:

答案 0 :(得分:3)

可以通过AnnotatedType层次结构检索所有类型注释,TypeVariable除外,AnnotatedTypeVariable.getType()的注释可以通过TypeVariable检索,AnnotatedElementMethod.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是否真的有Type

当然,这是仅处理您特定方法的“简化”版本。

要处理所有可能的情况,您需要更多AnnotatedType来处理TypeVariableAnnotatedElement的这些析取类型层次结构,尤其是在处理带注释的参数化类型和带注释的通用数组时类型。

如前所述,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()); 并且还有function something(pages,totalDutation){ // pages = 900 // totalDutation = 90 var printsPerMinute = pages / totalDutation //get the prints per minute! var printsPerHour = Math.floor(printsPerMinute * 60) //calculate the prints made in one hour var countOfHours = parseInt(totalDutation / 60) //divide the total duration by 60 to get the count of hours var remainingPrints = (totalDutation % 60) * printsPerMinute //add the extra prints that didn't complete a whole hour. var result = Array(countOfHours).fill(printsPerHour) //create an array and fill it. if(remainingPrints) result.push(remainingPrints) return result }方法。因此,在这种特定情况下,处理该方法的另一种方法是

public String method1(someparameters) {
       //Calls methods of a different objects
       result2 = object2.method2(someparams )
       result3 = object3.method3(someparams)
       // Does bunch of work in method1
       ...................
       ...................
       return result
 }