数组上的 Java 注释目标 ElementType.TYPE_USE

标签 java arrays reflection annotations java-8

使用新的 Java 8 ElementType.TYPE_USE选项,除了许多其他巧妙的事情之外,还可以注释(多维)数组的每个组件。例如,现在我可以在一个简单的字符串数组中对整个类型 String[] 进行注释和内部组件类型 String 。所以我希望做这样的事情:

@MyAnnotation(0) private static (@MyAnnotation(1) String) [] strs0;

一如既往,我将注释放在类型之前。如果这些表达式中允许使用括号,那么它将完美地工作。然而,Java 似乎选择了另一种方法,这导致了一些问题。我必须写:

@MyAnnotation(0) private static String @MyAnnotation(1) [] strs1;

并假设 @MyAnnotation(0)适用于整个领域,并且 @MyAnnotation(1)只是为了 String ,即使它位于类型 String 之后 。这是对该声明的正确解释吗?

因为如果是这样,那么反射解析就会出现严重错误。例如,采用以下声明:

@MyAnnotation(0) private static String @MyAnnotation(1) [] @MyAnnotation(2) [] @MyAnnotation(3) [] strs2;

人们会假设 @MyAnnotation(0)指整个字段,则@MyAnnotation(3)String[][]组件,@MyAnnotation(2)String[]组件,最后 @MyAnnotation(1)String成分。然而,当我们使用以下代码解析它时:

    Field field = Main.class.getDeclaredField("strs2");
    AnnotatedArrayType aat = (AnnotatedArrayType) field.getAnnotatedType();
    printAll(aat.getAnnotations());

    while (aat.getAnnotatedGenericComponentType() instanceof AnnotatedArrayType) {
        aat = (AnnotatedArrayType) aat.getAnnotatedGenericComponentType();
        printAll(aat.getAnnotations());
    }

我们将会看到:

@MyAnnotation(1)
@MyAnnotation(2)
@MyAnnotation(3)

与我们预期的顺序相反 ( { 3, 2, 1 } )。如果我们要迭代矩阵的元素,同时迭代抛出注释,将它们应用到相应的元素,这尤其麻烦。当我们迭代时,我们会从最后一层到第一层,也就是说,我们会遍历所有 String[][][]获取每个 String[][] 。然后我们检查每个 String[][]并获取所有 String[] 。最后我们迭代String[] ,并得到每个 String .

这些反射(reflection)(没有双关语)让我思考我对这些 TYPE_USE 示例含义的解释是否正确。当然,我可以只迭代一次矩阵,堆叠注释对,然后重新工作,但 Java 总是如此简单和优雅,所以一定有一些我遗漏的东西,比如我们声明表达式的方式或方式整个事情都是需要解释的。

我想对每个数组组件进行注释的原因是为了制作一个验证框架。它在 List<> 上完美运行。类型,使用 AnnotatedParameterizedType 。我可以写@Required List<@Required List<@Required Map<@Required String, @Required String>>> data并以正确的其他方式检索这些注释,完全没有问题。奇怪的是,原始数组的行为似乎有所不同......

更多详细信息,已更新答案信息

例如,当我们写

@A List<@B ArrayList<@C LinkedList<@D Integer>>> matrix;

很明显@A涉及最外层List , @B -> ArrayList , @C -> LinkedList@D -> Integer ,因为注释就在声明的类型之前。但是当我们写

@A int @B [] @C [] @D [] matrix;

乍一看,注释似乎位于类型之后,例如:

@A (((int @B) [] @C) [] @D) [] matrix;

所以@B -> int , @C -> int[]@D -> int[][] 。问题是,我们必须这样看:

@A int (@B []) (@C []) (@D []) matrix;

然后如果我们知道当我们调用matrix[x]时,我们会得到一个int[][],所以@B -> int[][],而只有matrix[x][y][z]给出一个 int,所以 @D -> int。因此,相关关系存在于字段的用法中,而不是声明指令中。

这与List的方式不同。 s,因为有 @D注释就在 Integer 之前它所指的类型。这种差异可能只对通用列表有意义,并且可能不会发生在其他常见的通用场景中。

最佳答案

我没看出有什么问题。给定 String[][][] ,您将其描述为一个数组,其中组件是 String[][] 。这也是一个数组,其中组件是 String[] 。这也是一个数组,其中组件是 String

One would assume that @MyAnnotation(0) refers to the whole field, then @MyAnnotation(3) refers to the String[][] component, @MyAnnotation(2) refers to the String[] component, and finally @MyAnnotation(1) refers to the String component.

我不同意。所以,给定一个

@MyAnnotation(0) private static String @MyAnnotation(1) [] @MyAnnotation(2) [] @MyAnnotation(3) [] strs2;

您将其描述为一个用 @MyAnnotation(0) 注释的字段它是一个数组类型,其中分量是 String[][]注释为 @MyAnnotation(1) 。这也是一个数组,其中组件是 String[]注释为 @MyAnnotation(2) 。这也是一个数组,其中组件是 String注释为 @MyAnnotation(3)

When we iterate, we go though the last level to the first, that is, we go through all String[][][] getting each String[][]. Then we go over each String[][] and get all String[]. Finally we iterate over String[], and get each String

这看起来是倒退的。

关于数组上的 Java 注释目标 ElementType.TYPE_USE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25220215/

相关文章:

java - 从 JTable 获取数据到 jText 字段,但出现空指针异常

java - 没有连接池的 Web 应用程序的数据库连接

java - 如何纠正 LWUIT 中找不到符号错误?

java - 图像不覆盖同名

javascript - 对于按属性值

java - JNI : how to return byte array via java field?

JavaScript:如何从 5 维数组中删除 2 列?

java - 在检查Java中的某些条件后是否可以加载一些类字段和方法

java - 调用抛出 IllegalArgumentException : wrong number of arguments

c# - 如果在运行时只知道类型参数,如何调用泛型方法?