Java 注释反射排序

Java Annotations Reflection Ordering

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

这确实有点不明确。让我们从可重复注释的 Java 8 特性开始,因为它有一些特点:

JLS §9.7.5. Multiple Annotations of the Same Type:

The implicitly declared annotation is called the container annotation, and the multiple annotations of type T which appeared in the context are called the base annotations. The elements of the (array-typed) value element of the container annotation are all the base annotations in the left-to-right order in which they appeared in the context.

所以容器会按顺序提供重复的注解。

此外,AnnotatedElement 的文档指定:

For an invocation of get[Declared]AnnotationsByType( Class < T >), the order of annotations which are directly or indirectly present on an element E is computed as if indirectly present annotations on E are directly present on E in place of their container annotation, in the order in which they appear in the value element of the container annotation.

将这两个放在一起,这意味着像 @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).

很有意思,how that is achieved:

If annotations of the annotation type annotationClass are found to be both directly and indirectly present, then getDeclaredAnnotations() will get called to determine the order of the elements in the returned array.

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

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

这是从 Java 8 文档派生的,但是由于 Java 6 和 7 现在已经结束并且不会改变,因此观察到的行为他们的实现与至少 Java 8 保证的行为相匹配,可能足以依赖它。