Java注释目标是阵列上的ElementType.TYPE_USE

时间:2014-08-09 15:39:45

标签: java arrays reflection annotations java-8

使用新的Java 8的ElementType.TYPE_USE选项,可以在许多其他简洁的东西中注释(多维)数组的每个组件。例如,现在我可以在一个简单的String数组中注释整个类型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

这些反思(没有双关语)让我思考我对这些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 - &gt; int [] [],而只有矩阵[x] [y] [z]给出一个int,所以@D - &gt; INT。因此,共同关系在字段的用法中,而不是声明指令。

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

1 个答案:

答案 0 :(得分:3)

我没有看到任何错误。给定String[][][],您将其描述为数组,其中组件为String[][]。这也是一个数组,其中组件是String[]。这也是一个数组,其中组件是String

  

人们会认为@MyAnnotation(0)指的是整个领域   @MyAnnotation(3)引用String[][]组件,@MyAnnotation(2)   是指String[]组件,最后是@MyAnnotation(1)   到String组件。

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

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

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

  

当我们迭代时,我们通过最后一级到第一级,即我们   遍历所有String [] [] []获取每个String [] []。然后我们过去   每个String [] []并获取所有String []。最后我们迭代了   String [],并获取每个String

这似乎是倒退。