Annotation Type NonNull
-
@Documented @Target(TYPE_USE) @Retention(RUNTIME) public @interface NonNull
Indicates that the annotated type usage (commonly a parameter type or return type) is considered to excludenull
as a value; rarely needed within null-marked code.This annotation serves two primary purposes:
- To mark any sporadic non-null type usages inside a scope that is not ready to be fully
NullMarked
yet. - To perform a non-null projection of a type variable, explained below.
For a comprehensive introduction to JSpecify, please see jspecify.org.
Non-null projection
In the following example,
MyOptional
's type parameterT
accepts only non-null type arguments, butMyList
's type parameterE
will accept either a non-null or nullable type argument.// All the below is null-marked code class MyOptional<T> { ? } interface MyList<E extends @Nullable Object> { // Returns the first non-null element, if such element exists. MyOptional<E> firstNonNull() { ? } // problem here! } MyList<@Nullable String> maybeNulls = ? MyList<String> nonNulls = ?
Because
MyOptional
accepts only non-null type arguments, we need bothmaybeNulls.firstNonNull()
andnonNulls.firstNonNull()
to produce the same return type:MyOptional!<String!>
(see notation). However, as specified above, they won't do that. In fact, there is a problem with thefirstNonNull
signature, since the type argumentString?
would not meet the requirements ofMyOptional
's type parameter.The solution is to project the type argument to its non-null counterpart:
// Returns the first non-null element, if such element exists. MyOptional<@NonNull E> firstNonNull() { ? } // problem fixed!
Here,
@NonNull E
selects the non-null form of the type argument, whether it was already non-null or not, which is just what we need in this scenario.If
E
has a non-null upper bound, then the apparent projection@NonNull E
is redundant but harmless.Nullable projection serves the equivalent purpose in the opposite direction, and is far more commonly useful.
If a type variable has all its usages being projected in one direction or the other, it should be given a non-null upper bound, and any non-null projections can then be removed.
Where it is applicable
@NonNull
is applicable in all the same locations asNullable
. - To mark any sporadic non-null type usages inside a scope that is not ready to be fully