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

Hoy quería crear mi primera interfaz de anotación siguiendo esta documentación y obtuve el error de comstackción “Tipo inválido para miembro de anotación”:

public @interface MyAnnotation { Object myParameter; ^^^^^^ } 

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

Esto lo descubrí usando prueba y error:

String --> Válido

int --> válido

Integer --> Inválido (Sorprendentemente)

String[] --> Valid (Sorprendentemente)

Object --> Inválido

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

Está especificado por la sección 9.6.1 del JLS . Los tipos de miembros de anotación deben ser uno de:

  • primitivo
  • Cuerda
  • Clase
  • un Enum
  • otra anotación
  • 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.

Estoy de acuerdo con Skaffman por los tipos disponibles.

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

Por ejemplo, los siguientes están prohibidos:

 @MyAnnot("a" + myConstantStringMethod()) @MyAnnot(1 + myConstantIntMethod()) 

Además, no olvide que las anotaciones en sí mismas pueden ser parte de una definición de anotación . Esto permite anidar anotaciones simples, lo que es ú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 SimpleAnnotation es

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

y ComplexAnnotation es

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

Ejemplos tomados de: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

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

 @interface Decorated { Class decorator() } interface PropertyDecorator { String decorate(String value) } class TitleCaseDecorator implements PropertyDecorator { String decorate(String value) } class Person { @Decorated(decorator = TitleCaseDecorator.class) String name }