Estoy intentando agregar dos o más anotaciones del mismo tipo en un solo elemento, en este caso, un método. Aquí está el código aproximado con el que estoy trabajando:
public class Dupe {
public @interface Foo {
String bar();
}
@Foo(bar="one")
@Foo(bar="two")
public void haha() {}
}
Al compilar lo anterior, javac se queja de una anotación duplicada:
max @ upsight: ~ / trabajo / amanecer $ javac Dupe.java Dupe.java:5: anotación duplicada
¿Simplemente no es posible repetir anotaciones como esta? Hablando pedante, ¿no son las dos instancias de @Foo anteriores diferentes debido a que sus contenidos son diferentes?
Si lo anterior no es posible, ¿cuáles son algunas posibles soluciones?
ACTUALIZACIÓN: Me han pedido que describa mi caso de uso. Aquí va.
Estoy construyendo un mecanismo de sintaxis azucarado para "mapear" POJOs a almacenes de documentos como MongoDB. Quiero permitir que los índices se especifiquen como anotaciones en los captadores o definidores. Aquí hay un ejemplo artificial:
public class Employee {
private List<Project> projects;
@Index(expr = "project.client_id")
@Index(expr = "project.start_date")
public List<Project> getProjects() { return projects; }
}
Obviamente, quiero poder encontrar rápidamente instancias de Employee por varias propiedades de Project. Puedo especificar @Index dos veces con diferentes valores expr (), o tomar el enfoque especificado en la respuesta aceptada. Aunque Hibernate hace esto y no se considera un truco, creo que todavía tiene sentido permitir al menos tener múltiples anotaciones del mismo tipo en un solo elemento.
fuente
Respuestas:
No se permiten dos o más anotaciones del mismo tipo. Sin embargo, podrías hacer algo como esto:
public @interface Foos { Foo[] value(); } @Foos({@Foo(bar="one"), @Foo(bar="two")}) public void haha() {}
Sin embargo, necesitará un manejo dedicado de la anotación de Foos en el código.
por cierto, acabo de usar esto hace 2 horas para solucionar el mismo problema :)
fuente
@Foos([@Foo(bar="one"), @Foo(bar="two")])
. Ver groovy.codehaus.org/Annotations+with+GroovyRepetición de anotaciones en Java 8
En Java 8 (lanzado en marzo de 2014), es posible escribir anotaciones repetidas / duplicadas.
Consulte el tutorial Repetición de anotaciones .
Consulte la especificación, JEP 120: anotaciones repetidas .
fuente
Aparte de las otras formas mencionadas, hay una forma menos detallada en 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{ }
El ejemplo se obtiene de forma predeterminada,
FooContainer
como una anotaciónTanto la impresión anterior:
fuente
http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html
A partir de Java8, puede describir anotaciones repetibles:
@Repeatable(FooValues.class) public @interface Foo { String bar(); } public @interface FooValues { Foo[] value(); }
Nota,
value
es un campo obligatorio para la lista de valores.Ahora puede usar anotaciones repitiéndolas en lugar de llenar la matriz:
@Foo(bar="one") @Foo(bar="two") public void haha() {}
fuente
Como dijo sfussenegger, esto no es posible.
La solución habitual es crear una anotación "múltiple" , que maneja una matriz de la anotación anterior. Por lo general, se denomina igual, con un sufijo 's'.
Por cierto, esto es muy utilizado en grandes proyectos públicos (Hibernate por ejemplo), por lo que no debe considerarse un hack, sino una solución correcta para esta necesidad.
Dependiendo de sus necesidades, podría ser mejor permitir que su anotación anterior maneje múltiples valores .
Ejemplo:
public @interface Foo { String[] bars(); }
fuente
combinando las otras respuestas en la forma más simple ... una anotación con una lista simple de valores ...
@Foos({"one","two"}) private String awk; //... public @interface Foos{ String[] value(); }
fuente
Si solo tiene 1 parámetro "barra", puede nombrarlo como "valor". En este caso, no tendrá que escribir el nombre del parámetro cuando lo use de esta manera:
@Foos({@Foo("one"), @Foo("two")}) public void haha() {}
un poco más corto y ordenado, imho ..
fuente
En la versión actual de Java, pude resolver este problema con la siguiente anotación:
@Foo({"one", "two"})
fuente