Я пытаюсь наложить две или более аннотаций одного типа на один элемент, в данном случае метод. Вот примерный код, с которым я работаю:
public class Dupe {
public @interface Foo {
String bar();
}
@Foo(bar="one")
@Foo(bar="two")
public void haha() {}
}
При компиляции вышеуказанного javac жалуется на дублирующуюся аннотацию:
макс @ апсайт: ~ / работа / рассвет $ javac Dupe.java Dupe.java:5: повторяющаяся аннотация
Разве нельзя повторять подобные аннотации? Говоря педантично, разве два приведенных выше экземпляра @Foo не отличаются из-за того, что их содержимое отличается?
Если это невозможно, каковы возможные обходные пути?
ОБНОВЛЕНИЕ: меня попросили описать мой вариант использования. Вот оно.
Я создаю синтаксический сахарный механизм для «сопоставления» POJO с хранилищами документов, такими как MongoDB. Я хочу разрешить указывать индексы в виде аннотаций для геттеров или сеттеров. Вот надуманный пример:
public class Employee {
private List<Project> projects;
@Index(expr = "project.client_id")
@Index(expr = "project.start_date")
public List<Project> getProjects() { return projects; }
}
Очевидно, я хочу иметь возможность быстро находить экземпляры Employee по различным свойствам Project. Я могу либо дважды указать @Index с разными значениями expr (), либо воспользоваться подходом, указанным в принятом ответе. Несмотря на то, что Hibernate делает это, и это не считается взломом, я думаю, что все же имеет смысл хотя бы разрешить наличие нескольких аннотаций одного типа для одного элемента.
источник
Ответы:
Использование двух или более аннотаций одного типа не допускается. Однако вы можете сделать что-то вроде этого:
public @interface Foos { Foo[] value(); } @Foos({@Foo(bar="one"), @Foo(bar="two")}) public void haha() {}
Однако вам понадобится специальная обработка аннотации Foos в коде.
кстати, я использовал это 2 часа назад для решения той же проблемы :)
источник
@Foos([@Foo(bar="one"), @Foo(bar="two")])
. См. Groovy.codehaus.org/Annotations+with+GroovyПовторение аннотаций в Java 8
В Java 8 (выпущенной в марте 2014 г.) можно писать повторяющиеся / повторяющиеся аннотации.
См. Учебник « Повторяющиеся аннотации» .
См. Спецификацию JEP 120: Повторяющиеся аннотации .
источник
Помимо других упомянутых способов, в Java8 есть еще один менее подробный способ:
@Target(ElementType.TYPE) @Repeatable(FooContainer.class) @Retention(RetentionPolicy.RUNTIME) @interface Foo { String value(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface FooContainer { Foo[] value(); } @Foo("1") @Foo("2") @Foo("3") class Example{ }
Пример по умолчанию получает
FooContainer
в виде аннотацииОба приведенных выше текста:
источник
http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
Начиная с Java8, вы можете описывать повторяющиеся аннотации:
@Repeatable(FooValues.class) public @interface Foo { String bar(); } public @interface FooValues { Foo[] value(); }
Обратите внимание,
value
это обязательное поле для списка значений.Теперь вы можете использовать повторяющиеся аннотации вместо заполнения массива:
@Foo(bar="one") @Foo(bar="two") public void haha() {}
источник
По словам Сфуссенеггера, это невозможно.
Обычное решение - создать "множественную" аннотацию , которая обрабатывает массив предыдущей аннотации. Обычно он называется так же с суффиксом 's'.
Кстати, это очень часто используется в больших публичных проектах (например, Hibernate), поэтому его не следует рассматривать как взлом, а скорее как правильное решение для этой потребности.
В зависимости от ваших потребностей, может быть лучше разрешить предыдущей аннотации обрабатывать несколько значений .
Пример:
public @interface Foo { String[] bars(); }
источник
объединение других ответов в простейшую форму ... аннотацию с простым списком значений ...
@Foos({"one","two"}) private String awk; //... public @interface Foos{ String[] value(); }
источник
Если у вас есть только 1 параметр «bar», вы можете назвать его «значение». В этом случае вам вообще не придется писать имя параметра, когда вы используете его следующим образом:
@Foos({@Foo("one"), @Foo("two")}) public void haha() {}
немного короче и аккуратнее, имхо ..
источник
В текущей версии Java я смог решить эту проблему с помощью следующей аннотации:
@Foo({"one", "two"})
источник