Error setting default value for annotation field

Why am I getting the error "Attribute value must be constant." Not a null constant

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class<? extends Foo> bar() default null;// this doesn't compile } 
+61
java annotations default
Jul 24 '09 at 14:35
source share
6 answers

I don’t know why, but JLS is very clear:

  Discussion Note that null is not a legal element value for any element type. 

And the default item definition:

  DefaultValue: default ElementValue 

Unfortunately, I continue to discover that the new language features (Enums and now Annotations) have very useless compiler error messages when you do not meet the language specifications.

EDIT: A little googleing discovered after in JSR-308, where they claim to allow zeros in this situation:

We note some possible objections to the proposal.

The offer does nothing possible, which was impossible before.

The special value defined by the programmer provides better documentation than zero, which can mean "none", "uninitialized", null, etc.

Offer more error prone. It is much easier to forget to check for zero than to forget to check for an explicit value.

A sentence may make the standard idiom more detailed. Currently, only annotation users need to check their specific values. As part of this proposal, many annotation processing tools will need to check if the field value is null so that they do not select null pointer exception.

I think that only the last two points are related to "why not do it first." The last point, of course, creates a good point - the annotation processor should never worry that they will get zero in the annotation value. I am inclined to see that, since the work of annotation processors and other such infrastructure code requires such verification to make the developer code more clear, and not vice versa, but, of course, it would be difficult to justify its change.

+50
Jul 24 '09 at 15:03
source share

try it

 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class bar() default void.class; } 

It does not require a new class, and it is already a keyword in Java, which means nothing.

+45
Apr 24 '13 at 19:43
source share

It would seem to be illegal, although JLS is very fuzzy.

I messed up my memory to try and think about an existing annotation that contains the Class attribute for the annotation, and remembered that from the JAXB API:

 @Retention(RUNTIME) @Target({PACKAGE,FIELD,METHOD,TYPE,PARAMETER}) public @interface XmlJavaTypeAdapter { Class type() default DEFAULT.class; static final class DEFAULT {} } 

You can see how they were supposed to define a dummy static class to store the null equivalent.

Unpleasant.

+40
Jul 24 '09 at 14:43
source share

There seems to be another way to do this.

I don't like it either, but it might work.

 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SomeInterface { Class<? extends Foo>[] bar() default {}; } 

So basically you are creating an empty array. This seems to allow you to use the default value.

+9
Sep 02 '14 at 13:02
source share

This error message is misleading, but no, the null literal is not a constant expression, as defined in the Java Language Specification, here .

In addition, the Java Language Specification says

This is a compile-time error if the element type is not proportionate (Β§9.7) to the default value.

And to explain what that means

This is a compile-time error if the type of an element is not commensurate with the size of the element. The type of the element T is commensurate with the value of the element V if and only if one of the following conditions is satisfied:

  • [...]
  • V is not null .

So your element type is Class<? extends Foo> Class<? extends Foo> not commensurate with the default value, because this value is null .

+1
Dec 24 '16 at 1:02
source share
 Class<? extends Foo> bar() default null;// this doesn't compile 

As already mentioned, the Java language specification does not allow null values ​​in annotation defaults.

What I mean is to define the DEFAULT_VALUE constants at the top of the annotation definition. Something like:

 public static final String DEFAULT_VALUE = "__class-name-here__ default"; public String prefix() default DEFAULT_VALUE; 

Then in my code I do something like:

 if (myAnnotation.prefix().equals(MyAnnotation.DEFAULT_VALUE)) { ... } 

In your case with the class, I would simply define a marker class. Unfortunately, you do not have a constant for this, so you need to do something like:

 Class<? extends Foo> bar() default DefaultFoo.class; 

Your DefaultFoo class will be just an empty implementation so that the code can:

 if (myAnnotation.bar() == DefaultFoo.class) { ... } 

Hope this helps someone else.

0
Jul 07 '17 at 15:42
source share



All Articles