为什么嵌套类型不能看到泛型类型参数的注释?

Tom*_*ský 6 java generics reflection annotations java-8

我没有得到以下代码的行为:https: //gist.github.com/tomaszalusky/3e3777b4fd0c6096f3f707bb19b50b52 - 请参阅embedded:

import java.lang.reflect.*;
import java.util.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


public class AnnotationOnTypeArgument {

    @Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.METHOD,ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Anno {

    }

    interface Nested<T> {

    }

    Toplevel<@Anno Integer> toplevel;

    Nested<@Anno Integer> nested;

    public static void main(String[] args) throws Exception {
        print(AnnotationOnTypeArgument.class.getDeclaredField("toplevel"));
        print(AnnotationOnTypeArgument.class.getDeclaredField("nested"));
    }

    private static void print(Field field) {
        AnnotatedType annotatedType = field.getAnnotatedType();
        AnnotatedParameterizedType annotatedParameterizedType = (AnnotatedParameterizedType)annotatedType;
        ParameterizedType parameterizedType = (ParameterizedType)annotatedParameterizedType.getType();
        AnnotatedType argType = annotatedParameterizedType.getAnnotatedActualTypeArguments()[0];
        System.out.printf("field %s%ntype=%s%nannotatedType=%s%nannotations=%s%ntype=%s%n%n",
                field.getName(), parameterizedType, argType, Arrays.asList(argType.getDeclaredAnnotations()), argType.getType());
    }

}

interface Toplevel<T> {

}
Run Code Online (Sandbox Code Playgroud)

编辑:实际结果是:

field toplevel
type=Toplevel<java.lang.Integer>
annotatedType=sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@1540e19d
annotations=[@AnnotationOnTypeArgument$Anno()]
type=class java.lang.Integer

field nested
type=AnnotationOnTypeArgument.AnnotationOnTypeArgument$Nested<java.lang.Integer>
annotatedType=sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@677327b6
annotations=[]
type=class java.lang.Integer
Run Code Online (Sandbox Code Playgroud)

当嵌套类型嵌套时,为什么类型参数上声明的注释数组为空?我希望有一个元素就像顶级类型一样.我将不胜感激任何基于JLS的解释.

在JDK8u101(http://compilejava.net),旧版JDK8和Eclipse 上始终如一.

谢谢!

Raf*_*ter 6

这是 OpenJDK 中的一个错误,我之前已经报告过这个问题,我希望它得到修复。类型注释在实践中并没有真正使用那么多,它似乎不是一个优先事项。正如 Holger 所提到的,这是AnnotatedTypeFactory.

您可以使用Byte Buddy正确解析类文件元数据:

public static void main(String[] args) throws Exception {

    TypeDescription type = TypePool.Default.ofClassPath()
       .describe(AnnotationOnTypeArgument.class.getName())
       .resolve();

    print(type.getDeclaredFields().filter(named("toplevel")).getOnly());
    print(type.getDeclaredFields().filter(named("nested")).getOnly());
}

private static void print(FieldDescription field) {
    System.out.printf("field %s%ntype=%s%nannotations=%s%ntype=%s%n%n",
            field.getName(),
            field.getType(),
            field.getType().getTypeArguments().get(0),
            field.getType().getTypeArguments().get(0).getDeclaredAnnotations());
}
Run Code Online (Sandbox Code Playgroud)

这为您提供了预期的输出:

field toplevel
type=net.bytebuddy.Toplevel<java.lang.Integer>
annotations=class java.lang.Integer
type=[@net.bytebuddy.AnnotationOnTypeArgument$Anno()]

field nested
type=net.bytebuddy.AnnotationOnTypeArgument.net.bytebuddy.AnnotationOnTypeArgument$Nested<java.lang.Integer>
annotations=class java.lang.Integer
type=[@net.bytebuddy.AnnotationOnTypeArgument$Anno()]
Run Code Online (Sandbox Code Playgroud)


ham*_*est 5

我给了一些时间进行调试,annotatedParameterizedType变量似乎仍然在其allOnSameTargetTypeAnnotations字段中包含对于嵌套情况的Anno注释的引用

annotatedParameterizedType = {AnnotatedTypeFactory$AnnotatedParameterizedTypeImpl@539} 
 type = {ParameterizedTypeImpl@540} "com.sample.Toplevel<java.lang.Integer>"
 decl = {Field@538} "com.sample.Toplevel com.sample.AnnotationOnTypeArgument.toplevel"
 location = {TypeAnnotation$LocationInfo@543} 
  depth = 0
  locations = {TypeAnnotation$LocationInfo$Location[0]@549} 
 allOnSameTargetTypeAnnotations = {TypeAnnotation[1]@544} 
  0 = {TypeAnnotation@551} "@com.sample.AnnotationOnTypeArgument$Anno() with Targetnfo: FIELD: -2, -2 on base declaration: com.sample.Toplevel com.sample.AnnotationOnTypeArgument.toplevel"
 annotations = {LinkedHashMap@546}  size = 0
Run Code Online (Sandbox Code Playgroud)

VS

annotatedParameterizedType = {AnnotatedTypeFactory$AnnotatedParameterizedTypeImpl@602} 
 type = {ParameterizedTypeImpl@603} "com.sample.AnnotationOnTypeArgument.com.sample.AnnotationOnTypeArgument$Nested<java.lang.Integer>"
 decl = {Field@601} "com.sample.AnnotationOnTypeArgument$Nested com.sample.AnnotationOnTypeArgument.nested"
 location = {TypeAnnotation$LocationInfo@606} 
  depth = 1
  locations = {TypeAnnotation$LocationInfo$Location[1]@611} 
 allOnSameTargetTypeAnnotations = {TypeAnnotation[1]@607} 
  0 = {TypeAnnotation@612} "@com.sample.AnnotationOnTypeArgument$Anno() with Targetnfo: FIELD: -2, -2 on base declaration: com.sample.AnnotationOnTypeArgument$Nested com.sample.AnnotationOnTypeArgument.nested"
 annotations = {LinkedHashMap@608}  size = 0 
Run Code Online (Sandbox Code Playgroud)

但是位置深度存在差异,AnnotatedTypeFactory的即将到来的getAnnotatedActualTypeArguments()方法包含一个TypeAnnotation.isSameLocationInfo()比较,作为向注释图添加元素的前提条件,在嵌套的情况下将变为false,因此最终没有元素正在增加

我也没有找到任何文件.也许你在这里找到了一个问题

  • 我想,我们可以追溯到[`AnnotatedTypeFactory`,第105行](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/reflect/ annotation/AnnotatedTypeFactory.java#105)其中嵌套的参数化类型被无条件地视为(非"静态")内部类(与可再生类型不同,前面有七行).事实上,询问`ParametertrizedType`是否是'静态',不是直截了当的...... (2认同)