使用新的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
类型之前。这种差异可能仅对通用列表有意义,并且可能不会出现在其他常见的通用场景中。
答案 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
这似乎是倒退。