Today I wanted to create my first annotation interface following this documentation and I got this compiler error
Invalid type for annotation member": public @interface MyAnnotation { Object myParameter; ^^^^^^ }
Obviously Object
cannot be used as type of an annotation member. Unfortunately I could not find any information on which types can be used in general.
This I found out using trial-and-error:
String → Valid
int → Valid
Integer → Invalid (Surprisingly)
String[] → Valid (Surprisingly)
Object → Invalid
Perhaps someone can shed some light on which types are actually allowed and why.
It's specified by section 9.6.1 of the JLS. The annotation member types must be one of:
primitive
String
an Enum
another Annotation
Class
an array of any of the above
It does seem restrictive, but no doubt there are reasons for it.
Also note that multidimensional arrays (e.g. String[][]
) are implicitly forbidden by the above rule.
Arrays of Class are not allowed as described in this answer.
I agree with Skaffman for the Types available.
Additional restriction : it has to be a compile-time constant.
For example, the following are forbidden:
@MyAnnot("a" + myConstantStringMethod())
@MyAnnot(1 + myConstantIntMethod())
Also don't forget that annotations themselves can be part of an annotation definition. This allows some simple annotation nesting - handy in cases where you would like to have one annotation present many times.
For example:
@ComplexAnnotation({
@SimpleAnnotation(a="...", b=3),
@SimpleAnnotation(a="...", b=3),
@SimpleAnnotation(a="...", b=3)
})
public Object foo() {...}
where SimpleAnnotation
is
@Target(ElementType.METHOD)
public @interface SimpleAnnotation {
public String a();
public int b();
)
and ComplexAnnotation
is
@Target(ElementType.METHOD)
public @interface ComplexAnnotation {
public SimpleAnnotation[] value() default {};
)
Examples taken from: http://web.archive.org/web/20131216093805/https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations
(original URL: https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations)
@Repeatable
, this is not needed anymore.
The concept of annotations fits really well with the design of my project, until I realized you can't have complex datatypes in the annotation. I got around it by using the class of what I wanted to instantiate rather than an instantiated object of that class. It's not perfect, but java rarely is.
@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
}
According to Oracle the valid types for annotation elements are:
1. Primitives (byte, char, int, long float, double)
2. Enums
3. Class (Think generics here Class <?>, Class<? extends/super T>>)
4. String
5. Array of the above (array[] of primitives, enums, String, or Class)
5. Another annotation.
A plus to note, all elements are inherently considered public and abstract.
Therefore
static final variable(s) allowed as well.
Success story sharing