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 (e.g. -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;
}