Search code examples
javanullannotationsdefault-value

Why is null forbidden as default value in annotations?


According to Annotation default "null" value, null values are forbidden as default values in annotations. I wonder why. What is the reason for that?


Solution

  • Note that null is not only unsupported as default value, it is unsupported as annotation value in general.

    JLS §9.7.1 specifies:

    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.29).
      • 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.

    The last bullet forbidding null may look arbitrary, but even without that bullet, null would not be a legal value as it is neither, a constant expression, a class literal, nor an enum constant.

    So the last bullet only makes it explicit that this is not an oversight.

    When annotations were added to the language, the definition of compile-time constants did already exist, including a bytecode format to store them. Class literals also were syntactically defined, though not on par with constants. But with JDK-4662563, their bytecode format became equivalent to that of other constants in the same version. So the support for class literals was natural for annotations as well.

    The only features uniquely added for annotation support were references to enum constants and a storage format for arrays. Both immediately proved their usefulness as the built-in annotations needed for the annotation definition itself, @Retention and Target, both use enum constants and the latter also uses arrays.

    So, null was not removed from the set of legal constructs, it has never been added. It was neither, straight-forward or natural to include nor immediately needed for the considered use cases.

    This answer shows that a suggestion to add support for null had been considered initially for the type annotation proposal (see also the archive link), with the objections named right at this point. As we all know, the type annotations were introduced with Java 8, support for null was not (Other suggestions, like repeatable annotations, made it into the language).