¿Qué tipos se pueden usar para los miembros de anotación Java?

238

Hoy quería crear mi primera interfaz de anotación siguiendo esta documentación y recibí este error de compilación

Invalid type for annotation member":
public @interface MyAnnotation {
    Object myParameter;
    ^^^^^^
}

Obviamente Objectno se puede usar como tipo de miembro de anotación. Lamentablemente, no pude encontrar ninguna información sobre qué tipos se pueden utilizar en general.

Esto lo descubrí usando prueba y error:

  • String → Válido
  • int → Válido
  • Integer → Inválido (Sorprendentemente)
  • String[] → Válido (Sorprendentemente)
  • Object → Inválido

Quizás alguien pueda arrojar algo de luz sobre qué tipos están realmente permitidos y por qué.

Daniel Rikowski
fuente
posiblemente varía según la anotación; muestre el código que está intentando escribir.
djna
2
Agregado a la pregunta. Pero no creo que varíe.
Daniel Rikowski

Respuestas:

324

Se especifica en la sección 9.6.1 de JLS . Los tipos de miembros de anotación deben ser uno de:

  • primitivo
  • Cuerda
  • una enumeración
  • otra anotación
  • Clase
  • una matriz de cualquiera de los anteriores

Parece restrictivo, pero sin duda hay razones para ello.

También tenga en cuenta que las matrices multidimensionales (por ejemplo String[][]) están implícitamente prohibidas por la regla anterior.

Las matrices de clase no están permitidas como se describe en esta respuesta .

skaffman
fuente
33
¿Cómo se encuentran esas páginas / documentos? Juro que siempre busco en Google antes de preguntar en StackOverlow y en muchas preguntas de Java, alguien publica un enlace al JSL que responde a mi pregunta. ¿Por qué no encuentro esas páginas a través de Google?
Daniel Rikowski
10
El JLS no es muy amigable con Google. Solo necesitas saber que está ahí.
skaffman
1
la misma información también está disponible en la guía de anotaciones en el sitio del sol (encontré ese google): java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
wds
1
Sí, también encontré esa página, pero debo haberme perdido esa oración, oculta en todo ese texto en prosa. He buscado algo más de mesa o de lista.
Daniel Rikowski
13
Lo que falta en la lista anterior es "Anotación". Puede tener una anotación que contenga otra anotación o una matriz de otra anotación.
Matt
58

Estoy de acuerdo con Skaffman para los tipos disponibles.

Restricción adicional: tiene que ser una constante de tiempo de compilación .

Por ejemplo, lo siguiente está prohibido:

@MyAnnot("a" + myConstantStringMethod())
@MyAnnot(1 + myConstantIntMethod())
KLE
fuente
31

Además, no olvide que las anotaciones en sí mismas pueden ser parte de una definición de anotación . Esto permite un anidamiento de anotaciones simple, útil en casos en los que le gustaría tener una anotación presente muchas veces.

Por ejemplo:

@ComplexAnnotation({
    @SimpleAnnotation(a="...", b=3),
    @SimpleAnnotation(a="...", b=3),
    @SimpleAnnotation(a="...", b=3)
})
public Object foo() {...}

donde SimpleAnnotationesta

@Target(ElementType.METHOD)
public @interface SimpleAnnotation {
    public String a();
    public int b();
)

y ComplexAnnotationes

@Target(ElementType.METHOD)
public @interface ComplexAnnotation {
    public SimpleAnnotation[] value() default {};
)

Ejemplos tomados de: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

(URL original: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations )

fikovnik
fuente
66
Con Java 8 @Repeatable, esto ya no es necesario.
Mordechai
11

El concepto de anotaciones encaja muy bien con el diseño de mi proyecto, hasta que me di cuenta de que no puede tener tipos de datos complejos en la anotación. Lo evité usando la clase de lo que quería instanciar en lugar de un objeto instanciado de esa clase. No es perfecto, pero Java rara vez lo es.

@interface Decorated { Class<? extends PropertyDecorator> decorator() }

interface PropertyDecorator { String decorate(String value) }

class TitleCaseDecorator implements PropertyDecorator {
    String decorate(String value)
}

class Person {
    @Decorated(decorator = TitleCaseDecorator.class)
    String name
}
Josh
fuente