2015-01-21 100 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