with - override annotation java




¿Anotaciones múltiples del mismo tipo en un elemento? (5)

Intento incluir 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:

[email protected]:~/work/daybreak$ javac Dupe.java 
Dupe.java:5: duplicate annotation

¿Simplemente no es posible repetir anotaciones como esta? Pedadicamente hablando, ¿no son las dos instancias de @Foo superiores diferentes debido a que sus contenidos son diferentes?

Si lo anterior no es posible, ¿cuáles son algunas soluciones posibles?

ACTUALIZACIÓN: me han pedido que describa mi caso de uso. Aquí va.

Estoy construyendo un mecanismo de sintaxis sugarish para "mapear" POJOs para documentar tiendas como MongoDB. Quiero permitir que los índices se especifiquen como anotaciones en los getters o setters. 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 instancias de Employee rápidamente por varias propiedades de Project. Puedo especificar @Index dos veces con diferentes valores de expr () o tomar el enfoque especificado en la respuesta aceptada. Aunque Hibernate hace esto y no se considera un hack, creo que todavía tiene sentido permitir al menos tener varias anotaciones del mismo tipo en un solo elemento.


Además de las otras formas mencionadas, hay una manera 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 de forma predeterminada obtiene, FooContainer como una anotación

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

Tanto la impresión de arriba:

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

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


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. Suele llamarse 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 como un hack, sino como 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();
    }

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ás 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 :)


Si tiene solo 1 parámetro "bar" puede nombrarlo como "valor". En este caso, no tendrá que escribir el nombre del parámetro cuando lo use así:

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

un poco más corto y más ordenado, imho ..


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();
}

Tenga en cuenta que el 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() {}






annotations