Daniel Rikowski
Daniel Rikowski

Reputation: 72534

Which types can be used for Java annotation members?

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:

Perhaps someone can shed some light on which types are actually allowed and why.

Upvotes: 308

Views: 141899

Answers (4)

skaffman
skaffman

Reputation: 403581

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
  • java.lang.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.

Upvotes: 407

Amos Kosgei
Amos Kosgei

Reputation: 947

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.

Upvotes: 4

fikovnik
fikovnik

Reputation: 3603

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)

Upvotes: 42

Josh
Josh

Reputation: 169

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
}

Upvotes: 16

Related Questions