Annotation Interface Nullable
null as a
value.
Example usages:
@Nullable String field;
@Nullable String getField() { return field; }
void setField(@Nullable String value) { field = value; }
List<@Nullable String> getList() { … }
For important information common to all four nullness annotations, see org.jspecify.annotations. To learn more about JSpecify, see jspecify.dev.
Meaning for each kind of type usage
Despite the itemized list here, the essential meaning of this annotation is always the same in
every case: the type it annotates is considered to include null as a value. A good way to
read @Nullable String in any context is "string-or-null". That's usually all you
need to think about, but this section offers some additional explanation for each kind of
context.
- On a parameter type: See the
setFieldexample above. It permissively accepts a "string-or-null", meaning that it is okay to pass an actual string, or to passnull. (This does not guarantee that passingnullwon't produce an exception at runtime. Why?) Lambda expression parameters work in the same way if their types are written explicitly. - On a method return type: See the
getFieldexample above. It returns a "string-or-null", so while the caller might get a real string back, it might getnullas well, and should be prepared for that possibility. - On a field type: See the
fieldexample above. It has the type "string-or-null", so it might hold a string and it might holdnull. (If you are confident the containing object can't be observed in its uninitialized state, the field need not be annotated solely because it is null during initialization.) - On a type argument: Within the compound type
MyList<@Nullable String>, we can see a usage of the type "string-or-null". To understand what@Nullablemeans here, read theMyList<E>API; every appearance you see of theEtype will be treated as nullable (unless it has its own nullness annotation, which takes precedence). For a typical container type like this example, this means it can contain null elements; if your list itself might be null as well, we can write@Nullable MyList<@Nullable String>: a nullable list of nullable strings. - On the upper bound of a type parameter: For example, consider
interface List<E extends @Nullable String>. This means that type arguments in that position may be nullable (as inList<@Nullable String>). A non-null type argument, as inList<String>, is permitted either way. - On a usage of a type variable: A type parameter, like
the
Tdeclared inclass Optional<T>, introduces a type variable of the same name, usable only within the scope of the declaring API element. All the preceding examples usingStringare equally valid for a type variable likeE.@Nullablecontinues to mean "or null" as always, regardless of whether the type argument "already" includesnull. For example, suppose thatclass Foo<E extends @Nullable Object>has a method@Nullable E eOrNull(). Then, whether a variablefoois of typeFoo<String>orFoo<@Nullable String>, the expressionfoo.eOrNull()is nullable either way. Using@Nullable Ein this way is called nullable projection. - On an array type: The nullness of the array and of its components can each be
indicated separately. For example, in null-marked context,
@Nullable String[]is a non-null array of nullable strings, andString @Nullable []is a nullable array of non-null strings. - On a varargs parameter: Use
@Nullable String...to indicate that the individual strings may be null. To letnullbe passed as the entire array, useString @Nullable .... - On a nested type: In most examples above, in place of
Stringwe might use a nested type such asMap.Entry. The Java syntax for annotating such a type as nullable looks likeMap.@Nullable Entry. - On a record component: Java propagates all type-use annotations (including
@Nullable) from a record component type to the type of the generated field, accessor method, and/or constructor parameter. If the constructor parameter list or accessor method is provided explicitly, it must still be annotated explicitly.
Where it is not applicable
This annotation and NonNull are applicable to any type usage except the
following cases, where they have no defined meaning and should not be used:
- On any intrinsically non-null type usage: one that is incapable of including
nullby the rules of the Java language, like the type followingthrows. A nullness annotation in this location could only be either contradictory or redundant. - On a local variable declaration (root type only). While the cases listed above benefit from declarative nullness, the nullness of a local variable is more properly determined through flow analysis (Why?). This rule applies only to the root type of the variable; type components, such as type arguments, follow the usual rules.
- In a cast expression (root type only). To inform an analyzer that an expression it
sees as nullable is truly non-null, use an assertion or a method like
Objects.requireNonNull(T). (Why?) Type components, such as type arguments, follow the usual rules. - On any part of the argument to
instanceof. The root type is intrinsically non-null, as discussed above, and nothing else about nullness is checked at runtime. - On any part of a receiver parameter type (JLS 8.4).
- If both
@Nullableand@NonNullappear on the same type usage, neither one is recognized.
Unannotated type usages
For a type usage where nullness annotations are applicable but
not present, its nullness depends on whether it appears within null-marked context; see NullMarked for details. Note in particular that nullness information from a superclass is never
automatically "inherited." (Why?)