【问题标题】:Why annotation on generic type argument is not visible for nested type?为什么泛型类型参数的注释对于嵌套类型不可见?
【发布时间】:2016-10-10 07:02:31
【问题描述】:

我没有得到以下代码的行为: https://gist.github.com/tomaszalusky/3e3777b4fd0c6096f3f707bb19b50b52 - 见嵌入:

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> {

}

编辑:实际结果是:

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

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

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

谢谢!

【问题讨论】:

    标签: java generics reflection annotations java-8


    【解决方案1】:

    这是 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());
    }
    

    这会给你预期的输出:

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

    【讨论】:

    • Rafael,你的意思是这个漏洞以前不为人所知?您能否指定报告的错误的 URL? Oracle 错误数据库搜索引擎目前似乎有些不健康。
    • 我试图找到它,但我找不到。我通过网络表格报告了它,所以我的名字不在问题上。我已经报告了大约 20 个与类型注释相关的错误,所以它很重要,抱歉。不幸的是,它们非常有缺陷。这份报告到现在应该已经有一年了。
    • 您好 Rafael,您能再次尝试查找错误报告吗?我正在考虑是否应该为a similar issue 提交报告。
    【解决方案2】:

    我花了一些时间进行调试,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
    

    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 
    

    但是位置深度有所不同,AnnotatedTypeFactory 即将推出的 getAnnotatedActualTypeArguments() 方法包含一个 TypeAnnotation.isSameLocationInfo() 比较作为向注释映射添加元素的前提条件,在嵌套情况下将变为 false,因此最终没有添加任何元素

    我也没有找到任何文档。也许你在这里发现了一个问题

    【讨论】:

    • 我认为,我们可以将其追溯到AnnotatedTypeFactory, line 105,其中嵌套的参数化类型被无条件地视为(非static)内部类(与可具体化类型不同,七行之前)。其实问一个ParametertrizedType是不是static,也不是直截了当……
    猜你喜欢
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 2018-07-23
    相关资源
    最近更新 更多