2015-01-21 101 views
8

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

+1

我很想知道这个我自己特别是用java 8 @Repeatable – 2015-01-21 13:07:16

+0

我在问自己同样的问题 - 到目前为止我找不到任何明确的声明。有关这方面的消息吗? – mkurz 2015-04-10 09:11:45

+1

@Adam Gent,@mkurz:至少对于可重复的注释,规范中有一些明确的词,我将它们组合在一起。他们甚至允许关于'getDeclaredAnnotations()'的原始问题的结论。 – Holger 2015-05-13 18:26:28

回答

9

这确实有点低估。让我们先从重复标注在Java 8的功能,因为有一些关于它的位:

JLS §9.7.5. Multiple Annotations of the Same Type

隐式声明的注释被称为容器注释T类型的多个批注其出现在上下文中称为基注释。容器注释(array-typed)value元素的元素是它们在上下文中出现的从左到右顺序的所有基本注释。

所以容器将按顺序提供重复的注释。

此外,的AnnotatedElement的文档指定:

对于get[Declared]AnnotationsByType(Class <T>)调用,注释,它们可直接或间接地存在的元素Ë被计算为,如果间接地存在注解E对的顺序直接出现在E中,取代它们的容器注释,按它们出现在容器注释的value元素中的顺序。

把他们俩撮合在一起,它意味着重复注解像@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

如果发现注释类型annotationClass的标注直接和间接现在是既,然后getDeclaredAnnotations()将被调用,以确定返回数组中的元素的顺序。

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

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

这是从Java 8文档中派生出来的,但是因为Java 6和7现在已经达到其生命周期并且不会改变,所以观察到的实现行为与在至少对于Java 8来说,可能足以依赖它。

+1

非常感谢您为您提供的精彩而全面的答案。 – 2015-05-14 09:01:54

+0

感谢您的详细解答!这是我所能找到的第一个声明,它清楚而逻辑地说明了通过getDeclaredAnnotations()检索注释的顺序 - 我已经完成了一些研究......非常感谢! – mkurz 2015-05-14 13:08:32

+0

我不认为你可以依靠一个微妙的暗示,而不是直接说明保持订单的方法的契约。如果这是“某人忘记在文档中提到它”的情况,那么这已经是固定的了。 直到它陷入困境时,对未来仍然保留的假设进行编码可能会破坏基于注释的功能。 – 2017-02-14 01:11:01