fge
fge

Reputation: 121730

How to make a @Documented annotation retaining generics information?

I currently have this annotation defined:

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@Beta
public @interface Needs
{
    Class<?>[] value();
}

The problem is that while I can do:

@Needs({SomeClass.class, OtherClass.class})

I cannot do, for instance:

@Needs(Map<String, SomeClass>)

The purpose is to have it documented and retain generics information like the above. Is it possible?

Upvotes: 2

Views: 111

Answers (1)

meriton
meriton

Reputation: 70564

The Java Language Specification writes:

It is a compile-time error if the return type of a method declared in an annotation type is not one of the following: a primitive type, String, Class, any parameterized invocation of Class, an enum type (§8.9), an annotation type, or an array type (§10) whose element type is one of the preceding types.

The reason for this restriction is that annotation values are evaluated at compile time, and only the values are stored. Therefore, these values can not be arbitrary objects, because it would be unclear how to store them in the class file, and unmarshall them at runtime.

The usual solution is the nested annotation trick:

public @interface Needs {
    Need[] value();
}

public @interface Need {
    String key();
    Class value();
}

which you can then use like

@Needs([
    @Need(key = "aKey", value = A.class)
    @Need(key = "anotherKey", value = Another.class)
])

Upvotes: 2

Related Questions