简体   繁体   中英

Default null value for annotation fields in Java

I am creating a custom annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyFramework {

    public Integer index() default null; // Compiler complains here

}

The compiler complains that null is not allowed. I do not want to make the index field primitive type int as it would not make sense. Is there a way to have a default null value for annotation fields?

The answer at Error setting a default null value for an annotation's field mention about Class type so the solutions work, but not for Integer , Double etc.

You cannot use null as a default (or non-default) value. Using null is expressly forbidden by the Java Language Specification (JLS). From §9.6.2 of the JLS :

It is a compile-time error if the type of the element is not commensurate ( §9.7 ) with the default value specified.

And from §9.7.1 of the JLS :

It is a compile-time error if the element type is not commensurate with the element value. An element type T is commensurate with an element value V if and only if one of the following is true :

  • T is an array type E[] , and either:

    • If V is a ConditionalExpression or an Annotation , then V is commensurate with E ; or
    • If V is an ElementValueArrayInitializer , then each element value that V contains is commensurate with E .

      An ElementValueArrayInitializer is similar to a normal array initializer (§10.6), except that an ElementValueArrayInitializer may syntactically contain annotations as well as expressions and nested initializers. However, nested initializers are not semantically legal in an ElementValueArrayInitializer because they are never commensurate with array-typed elements in annotation type declarations (nested array types not permitted).

  • T is not an array type, and the type of V is assignment compatible (§5.2) with T , and:

    • If T is a primitive type or String , then V is a constant expression (§15.28).
    • If T is Class or an invocation of Class (§4.5), then V is a class literal (§15.8.2).
    • If T is an enum type (§8.9), then V is an enum constant (§8.9.1).
    • V is not null .

Note that if T is not an array type or an annotation type, the element value must be a ConditionalExpression (§15.25). The use of ConditionalExpression rather than a more general production like Expression is a syntactic trick to prevent assignment expressions as element values. Since an assignment expression is not a constant expression, it cannot be a commensurate element value for a primitive or String -typed element.

[...]

It's that last bullet point, " V is not null ", that's the reason for your compilation error.

If you want a default value that means "not set" then use a non-null sentinel value. For instance, if a negative number is never a valid value then you can use any negative number (eg -1 , Integer.MIN_VALUE , etc.) as a default value. For example:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyFramework {

  // note the "public" modifier is implicitly added
  Integer index() default Integer.MIN_VALUE;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM