Java 注解反射排序
当通过反射访问定义在字段上的注释时(即使用 getDeclaredAnnotations() : Annotation[]
方法),Java 6 或 7 规范是否对注释的顺序做出任何保证回.我已经检查了相关的 java 文档,但似乎找不到明确的答案.
When accessing Annotations defined on a Field via Reflection (i.e using the getDeclaredAnnotations() : Annotation[]
method) does the Java 6 or 7 specification make any guarantees about the order in which the Annotations are returned. I have examined the relevant java docs but can't seem to find a definitive answer.
推荐答案
这确实有点未指定.让我们从可重复注释的 Java 8 特性开始,因为它有一些细节:
That’s indeed a bit underspecified. Let’s start with the Java 8 feature of repeatable annotations as there are some bits about it:
JLS §9.7.5.同一类型的多个注解:
隐式声明的注解称为容器注解,而出现在上下文中的多个T
类型的注解称为基础注解.容器注解的(数组类型的)value
元素的元素都是基础注解,按照它们在上下文中出现的从左到右的顺序排列.
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.
所以容器会按顺序提供重复的注解.
So the container will provide the repeated annotations in order.
另外, 的文档AnnotatedElement
指定:
Additionally, the documentation of AnnotatedElement
specifies:
对于 get[Declared]AnnotationsByType(Class < T >)
的调用,直接或间接存在于元素 E 上的注释顺序为就像在 E 上间接存在的注解直接出现在 E 上一样代替它们的容器注解,按照它们出现在容器注解的 value 元素中的顺序进行计算.
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()
直接处理显示该顺序的注释.
Putting these two together, it implies that repeated annotations like @Foo(1) @Foo(2) @Foo(3)
are stored like you had written @FooContainer({@Foo(1), @Foo(2), @Foo(3)})
and the latter, regardless of how it was originally created, will be treated by getDeclaredAnnotations()
like directly present annotations of that order.
所以重复注释的答案是顺序将是它们出现的从左到右的顺序".
So the answer for repeated annotations is that the order will be the "left-to-right order in which they appeared".
但是我们可以从AnnotatedElement
的文档中得出另一个结论.由于它声明注释的顺序是按照间接存在的注释直接存在于它们的容器注释的位置来计算的,这意味着如果您编写 @Foo(1) @FooContainer({@Foo(2), @Foo(3)})
或 @FooContainer({@Foo(1), @Foo(2)}) @Foo(3)
,顺序将与元素相同容器将替换它,就像您编写 @Foo(1) @Foo(2) @Foo(3)
一样.
But there is another conclusion we can draw from the documentation of AnnotatedElement
. Since it states that the order of annotations is computed as if indirectly present annotations are directly present in place of their container annotation, it implies that if you write @Foo(1) @FooContainer({@Foo(2), @Foo(3)})
or @FooContainer({@Foo(1), @Foo(2)}) @Foo(3)
, the order will be the same as the elements of the container will replace it just as had you written @Foo(1) @Foo(2) @Foo(3)
.
这很有趣,如何实现:
如果发现注释类型 annotationClass 的注释直接和间接存在,则将调用 getDeclaredAnnotations()
以确定返回数组中元素的顺序.
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()
具有可靠顺序的指标.它用于确定履行上述合同所需的订单.
This implementation note is the first indicator within the entire documentation that getDeclaredAnnotations()
has a reliable order. It is used to determine the order that is required to fulfill the contract described above.
所以答案是,是的,getDeclaredAnnotations()
以有保证的顺序提供注释,但该信息并不直接附加到方法本身的文档中.
So the answer is, yes, getDeclaredAnnotations()
provides the annotations in a guaranteed order, but that information is not directly attached to the documentation of the method itself.
这源自 Java 8 文档,但由于 Java 6 和 7 现在已经到了生命周期的尽头并且不会改变,因此观察到的实现行为与至少保证的行为相匹配这一事实对于 Java 8,依赖它可能就足够了.
This is derived from the Java 8 documentation, but since Java 6 and 7 reached their end-of-life now and won’t change, the fact that the observed behavior of the their implementation matches the behavior that is guaranteed at least for Java 8, might be enough to rely on it.
相关文章