Java Annotations Reflection Ordering

2022-09-03 14:47:21

当通过反射(即使用该方法)访问在字段上定义的注释时,Java 6 或 7 规范是否会对注释的返回顺序做出任何保证。我已经检查了相关的java文档,但似乎找不到明确的答案。getDeclaredAnnotations() : Annotation[]


答案 1

这确实有点被低估了。让我们从可重复注释的Java 8功能开始,因为它有一些关于它的一些内容:

JLS §9.7.5.同一类型的多个注释

隐式声明的注释称为容器注释,出现在上下文中的多个类型注释称为基本注释。容器批注的(数组类型)元素的元素是所有基本批注,按它们在上下文中出现的从左到右的顺序排列。Tvalue

因此,容器将按顺序提供重复的注释。

此外,AnnotatedElement 的文档指定:

对于 的调用,直接或间接存在于元素 E 上的注释的顺序被计算,就好像 E 上间接存在的注释直接存在于 E 上,而不是它们的容器注释,按照它们在容器注释的值元素中出现的顺序。get[Declared]AnnotationsByType( Class < T >)

将这两者放在一起,这意味着重复的注释像你写的那样存储,而后者,无论它最初是如何创建的,都将被视为直接存在的注释。@Foo(1) @Foo(2) @Foo(3)@FooContainer({@Foo(1), @Foo(2), @Foo(3)})getDeclaredAnnotations()

因此,重复注释的答案是,顺序将是“它们出现的从左到右的顺序”。


但是,我们可以从 的文档中得出另一个结论。由于它指出注释的顺序是计算的,就好像间接存在的注释直接存在于其容器注释的位置一样,这意味着如果您编写或,则顺序将与容器的元素相同,就像您编写的那样替换它。AnnotatedElement@Foo(1) @FooContainer({@Foo(2), @Foo(3)})@FooContainer({@Foo(1), @Foo(2)}) @Foo(3)@Foo(1) @Foo(2) @Foo(3)

有趣的是,这是如何实现的

如果发现注释类型 annotationClass 的注释同时存在和间接存在,则将被调用以确定返回数组中元素的顺序。getDeclaredAnnotations()

此实现说明是整个文档中具有可靠订单的第一个指标。它用于确定履行上述合同所需的订单。getDeclaredAnnotations()

因此,答案是,是的,以保证的顺序提供注释,但该信息不直接附加到方法本身的文档。getDeclaredAnnotations()

这源于Java 8文档,但是由于Java 6和7现在已经达到了它们的生命周期并且不会改变,因此观察到的实现的行为与至少Java 8所保证的行为相匹配这一事实可能足以依赖它。


答案 2