2015-01-21 3 views
8

При использовании аннотаций, определенных в поле через Reflection (т. Е. С использованием метода getDeclaredAnnotations() : Annotation[]), спецификации Java 6 или 7 предоставляют какие-либо гарантии относительно порядка, в котором возвращаются аннотации. Я изучил соответствующие java-документы, но не могу найти окончательного ответа.Java Annotations Reflection Ordering

+1

Я сам это задавал особенно с java 8 @Repeatable –

+0

Я задавал себе тот же вопрос - пока я не нашел никакого ясного заявления. Любые новости об этом? – mkurz

+1

@Adam Gent, @mkurz: по крайней мере для повторяемых аннотаций, в спецификации есть несколько ясных слов, я собрал их вместе. Они даже позволяют сделать вывод об исходном вопросе относительно 'getDeclaredAnnotations()'. – Holger

ответ

9

Это действительно немного неопределенный. Давайте начнем с функцией Java 8 повторяемых аннотаций, поскольку есть некоторые биты о ней:

JLS §9.7.5. Multiple Annotations of the Same Type:

неявно объявлено аннотация называется контейнера аннотацией, а также несколько аннотаций типа T, которые появившиеся в контексте, называются аннотациями . Элементы элемента массива (массива) value аннотации контейнера являются базовыми аннотациями в порядке слева направо, в котором они появились в контексте.

Таким образом, контейнер предоставит повторяющиеся аннотации по порядку.

Кроме того, документация AnnotatedElement определяет:

Для вызова get[Declared]AnnotationsByType(Class <T>), порядок аннотаций, которые прямо или косвенно присутствует на элементе Е вычисляется, как если бы косвенно настоящие аннотации на E непосредственно присутствуют на E вместо их аннотации к контейнеру в том порядке, в котором они отображаются в элементе значения аннотации контейнера.

Положив эти два вместе, это означает, что повторные аннотации как @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

Благодарим вас за ваш хорошо представленный и исчерпывающий ответ. –

+0

Спасибо за подробный ответ! Это первое утверждение, которое я смог найти, который четко и логично говорит, в каком порядке аннотации извлекаются с помощью 'getDeclaredAnnotations()' - и я уже провел довольно много исследований ... Большое спасибо! – mkurz

+0

Я не думаю, что вы можете положиться на тонкий намек, не указав прямоту контракта на способ сохранения порядка. Если бы это было так, что «кто-то просто забыл упомянуть об этом в документах», это уже было бы исправлено. Пока он не установлен в камне, кодирование с предположением, что оно останется таким, в будущем может нарушить вашу функцию на основе аннотаций. –