¿Qué tipos se pueden utilizar para los miembros de anotaciones de Java?
Hoy quería crear mi primera interfaz de anotación siguiendo esta documentación y recibí este error del compilador.
Invalid type for annotation member": public @interface MyAnnotation { Object myParameter; ^^^^^^ }
Obviamente Object
no se puede utilizar 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álidoint
→ VálidoInteger
→ 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é.
Está especificado en la sección 9.6.1 de JLS . Los tipos de miembros de anotación deben ser uno de:
- primitivo
- Cadena
- una enumeración
- otra anotación
- clase java.lang.
- una matriz de cualquiera de los anteriores
Parece restrictivo, pero sin duda hay razones para ello.
Tenga en cuenta también que las matrices multidimensionales (p. ej. String[][]
) están implícitamente prohibidas por la regla anterior.
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 sencillo, lo que resulta útil en los casos en los que desea que una anotación esté presente muchas veces.
Por ejemplo:
@ComplexAnnotation({
@SimpleAnnotation(a="...", b=3),
@SimpleAnnotation(a="...", b=3),
@SimpleAnnotation(a="...", b=3)
})
public Object foo() {...}
dónde 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: 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 )
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<? 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
}