Which types can be used for Java annotation members?

JavaAnnotations

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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

Solution 3 - Java

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)

Solution 4 - Java

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
}

Solution 5 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel RikowskiView Question on Stackoverflow
Solution 1 - JavaskaffmanView Answer on Stackoverflow
Solution 2 - JavaKLEView Answer on Stackoverflow
Solution 3 - JavafikovnikView Answer on Stackoverflow
Solution 4 - JavaJoshView Answer on Stackoverflow
Solution 5 - JavaAmos KosgeiView Answer on Stackoverflow