Adam Arold
Adam Arold

Reputation: 30538

Why java annotation attributes have restrictions?

I noticed that if I create an annotation:

public @interface NullableTypeOverride {
    NullableType hibernateTypeOverride();
}

I have limited options for annotation attributes. The above code will not work because annotations only take primitive, String or Class types for their attributes.

So in this case I can't use this annotation like this:

@NullableTypeOverride(hibernateTypeOverride = Hibernate.INTEGER)
private Long distance;

My guess is that it has something to do with compile time vs. runtime but I'm not entirely sure. So what is the reason for this limitation and how can I work around it?

Upvotes: 7

Views: 1539

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279990

The JLS states

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 is that annotations must have a constant value. If you provide a reference to an object that may change, you'll have problems. This is only relevant if the annotation's Retention is RUNTIME.

public class Person {
    public String name;
}

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    Person person();
}

@MyAnnotation(person = ???) // how to guarantee it won't change at runtime?
public void method1()  {...}

What's that value supposed to be? And how can reflection libs cache it?

MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
annotation.person(); // should be the same value every time

Remember, annotations are supposed to be metadata.

Upvotes: 7

Related Questions