Próbuję uderzyć dwie lub więcej adnotacji tego samego typu na jednym elemencie, w tym przypadku na metodzie. Oto przybliżony kod, z którym pracuję:
public class Dupe {
public @interface Foo {
String bar();
}
@Foo(bar="one")
@Foo(bar="two")
public void haha() {}
}
Podczas kompilowania powyższego javac narzeka na zduplikowaną adnotację:
max @ upsight: ~ / work / daybreak $ javac Dupe.java Dupe.java:5: zduplikowana adnotacja
Czy po prostu nie można powtórzyć takich adnotacji? Mówiąc pedantycznie, czy te dwa wystąpienia @Foo powyżej nie są różne, ponieważ ich zawartość jest inna?
Jeśli powyższe nie jest możliwe, jakie są potencjalne obejścia?
UPDATE: Poproszono mnie o opisanie mojego przypadku użycia. Tutaj idzie.
Buduję mechanizm łagodnej składni, aby „mapować” POJO na magazyny dokumentów, takie jak MongoDB. Chcę zezwolić na określanie indeksów jako adnotacji na elementach pobierających lub ustawiających. Oto wymyślony przykład:
public class Employee {
private List<Project> projects;
@Index(expr = "project.client_id")
@Index(expr = "project.start_date")
public List<Project> getProjects() { return projects; }
}
Oczywiście chcę móc szybko znaleźć wystąpienia pracownika według różnych właściwości projektu. Mogę określić @Index dwukrotnie z różnymi wartościami wyrażenia () lub zastosować podejście określone w zaakceptowanej odpowiedzi. Mimo że Hibernate to robi i nie jest to uważane za hack, myślę, że warto przynajmniej zezwolić na posiadanie wielu adnotacji tego samego typu na jednym elemencie.
źródło
Odpowiedzi:
Dwie lub więcej adnotacji tego samego typu są niedozwolone. Możesz jednak zrobić coś takiego:
public @interface Foos { Foo[] value(); } @Foos({@Foo(bar="one"), @Foo(bar="two")}) public void haha() {}
Będziesz jednak potrzebować dedykowanej obsługi adnotacji Foos w kodzie.
btw, właśnie użyłem tego 2 godziny temu, aby obejść ten sam problem :)
źródło
@Foos([@Foo(bar="one"), @Foo(bar="two")])
. Zobacz groovy.codehaus.org/Annotations+with+GroovyPowtarzanie adnotacji w Javie 8
W Javie 8 (wydanej w marcu 2014) możliwe jest pisanie powtarzających się / zduplikowanych adnotacji.
Zobacz samouczek Powtarzanie adnotacji .
Patrz specyfikacja, JEP 120: Powtarzanie adnotacji .
źródło
Oprócz innych wymienionych sposobów, w Javie8 jest jeszcze jeden mniej rozwlekły sposób:
@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{ }
Przykład domyślnie pobiera
FooContainer
jako adnotacjaObie powyższe wydruki:
źródło
http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
Począwszy od Java8 możesz opisywać powtarzalne adnotacje:
@Repeatable(FooValues.class) public @interface Foo { String bar(); } public @interface FooValues { Foo[] value(); }
Uwaga:
value
pole wymagane dla listy wartości.Teraz możesz używać adnotacji, powtarzając je zamiast wypełniania tablicy:
@Foo(bar="one") @Foo(bar="two") public void haha() {}
źródło
Jak powiedział sfussenegger, nie jest to możliwe.
Typowym rozwiązaniem jest utworzenie adnotacji „wielokrotnej” , która obsługuje tablicę poprzedniej adnotacji. Zwykle ma taką samą nazwę, z przyrostkiem „s”.
Nawiasem mówiąc, jest to bardzo używane w dużych projektach publicznych (na przykład Hibernate), więc nie powinno być traktowane jako hack, a raczej poprawne rozwiązanie na tę potrzebę.
W zależności od potrzeb może być lepiej, jeśli wcześniejsza adnotacja obsługiwała wiele wartości .
Przykład:
public @interface Foo { String[] bars(); }
źródło
połączenie innych odpowiedzi w najprostszą formę ... adnotacja z prostą listą wartości ...
@Foos({"one","two"}) private String awk; //... public @interface Foos{ String[] value(); }
źródło
Jeśli masz tylko 1 parametr „słupek”, możesz go nazwać „wartością”. W takim przypadku nie będziesz musiał w ogóle wpisywać nazwy parametru, gdy używasz jej w ten sposób:
@Foos({@Foo("one"), @Foo("two")}) public void haha() {}
trochę krótszy i schludniejszy, imho ...
źródło
W obecnej wersji Java udało mi się rozwiązać ten problem z następującą adnotacją:
@Foo({"one", "two"})
źródło