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



使用新的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

这些反思(没有双关语的意思)让我思考我对这些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;

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

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

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

可以假设@MyAnnotation(0)指的是整个字段@MyAnnotation(3)String[][]组件,@MyAnnotation(2)String[]组件,最后为@MyAnnotation(1)组件

我不同意。那么,给定一个

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

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

迭代时,从的最后一级到第一级,也就是我们遍历所有String[][][]获取每个String[][]。然后再看一遍每个String[][]并获取所有String[]。最后我们进行迭代字符串[],并获取每个String

相关内容

最新更新