Annotazioni multiple dello stesso tipo su un elemento?

Sto tentando di schiaffare due o più annotazioni dello stesso tipo su un singolo elemento, in questo caso, un metodo. Ecco il codice approssimativo con cui sto lavorando:

public class Dupe { public @interface Foo { String bar(); } @Foo(bar="one") @Foo(bar="two") public void haha() {} } 

Durante la compilazione di quanto sopra, javac si lamenta di un’annotazione duplicata:

 max @ upsight: ~ / work / daybreak $ javac Dupe.java 
 Dupe.java:5: annotazione duplicata

È semplicemente imansible ripetere annotazioni come questa? Pedanticamente parlando, le due istanze di @Foo non sono diverse a causa del fatto che i loro contenuti sono diversi?

Se quanto sopra non è ansible, quali sono alcune soluzioni alternative?

AGGIORNAMENTO: mi è stato chiesto di descrivere il mio caso d’uso. Ecco qui.

Sto costruendo un meccanismo di syntax sugarish per “mappare” POJOs per documentare negozi come MongoDB. Voglio consentire che gli indici siano specificati come annotazioni sui getter o setter. Ecco un esempio forzato:

 public class Employee { private List projects; @Index(expr = "project.client_id") @Index(expr = "project.start_date") public List getProjects() { return projects; } } 

Ovviamente, voglio essere in grado di trovare rapidamente le istanze di Dipendente da varie proprietà del Progetto. Posso specificare @Index due volte con valori diversi di expr () o adottare l’approccio specificato nella risposta accettata. Anche se Hibernate fa questo e non è considerato un hack, penso che abbia ancora senso permettere almeno di avere più annotazioni dello stesso tipo su un singolo elemento.

Due o più annotazioni dello stesso tipo non sono consentite. Tuttavia, potresti fare qualcosa del genere:

 public @interface Foos { Foo[] value(); } @Foos({@Foo(bar="one"), @Foo(bar="two")}) public void haha() {} 

Avrai però bisogno di una gestione dedicata dell’annotazione di Foos nel codice.

btw, ho appena usato questo 2 ore fa per aggirare lo stesso problema 🙂

In Java 8 (rilasciato a marzo 2014), è ansible scrivere annotazioni ripetute / duplicate. Vedi http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html .

http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

A partire da Java8 puoi descrivere annotazioni ripetibili:

 @Repeatable(FooValues.class) public @interface Foo { String bar(); } public @interface FooValues { Foo[] value(); } 

Nota, il value è un campo obbligatorio per la lista valori.

Ora puoi usare annotazioni ripetendole invece di riempire l’array:

 @Foo(bar="one") @Foo(bar="two") public void haha() {} 

Come detto da sfussenegger, questo non è ansible.

La solita soluzione è creare un’annotazione “multipla” , che gestisce un array della precedente annotazione. In genere viene chiamato lo stesso, con un suffisso “s”.

A proposito, questo è molto usato in grandi progetti pubblici (Hibernate per esempio), quindi non dovrebbe essere considerato come un hack, ma piuttosto una soluzione corretta per questa necessità.


A seconda delle esigenze, potrebbe essere meglio consentire all’annotazione precedente di gestire più valori .

Esempio:

  public @interface Foo { String[] bars(); } 

Oltre agli altri modi menzionati, c’è un altro modo meno dettagliato in 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{ } 

Esempio di default ottiene, FooContainer come FooContainer

  Arrays.stream(Example.class.getDeclaredAnnotations()).forEach(System.out::println); System.out.println(Example.class.getAnnotation(FooContainer.class)); 

Sia la stampa di cui sopra:

@ com.FooContainer (valore = [@ com.Foo (valore = 1), @ com.Foo (valore = 2), @ com.Foo (valore = 3)])

@ com.FooContainer (valore = [@ com.Foo (valore = 1), @ com.Foo (valore = 2), @ com.Foo (valore = 3)])

combinando le altre risposte nella forma più semplice … un’annotazione con un semplice elenco di valori …

 @Foos({"one","two"}) private String awk; //... public @interface Foos{ String[] value(); } 

Se hai solo 1 parametro “bar” puoi chiamarlo “valore”. In questo caso non dovrai scrivere il nome del parametro quando lo usi in questo modo:

 @Foos({@Foo("one"), @Foo("two")}) public void haha() {} 

un po ‘più corto e più ordinato, imho ..