This document describes the @NonNull
type annotation, and a
checker (a compiler plugin) for it.
If the checker issues no warnings for a given program, then running that program will never throw a null pointer exception. This guarantee enables a programmer to prevent errors from occurring when his program is run.
The non-null checking plugin is distributed as part of the JSR 308 checkers framework.
Contents:
@NonNull
@NonNull
In order to perform checking, you must annotate your code with the
@NonNull
type annotation, which indicates a type that does not
include the null
value. (You should also add
import checkers.quals.*;
at the top of your source file, to
permit use of @NonNull
.)
A variable of type
Boolean
always has one of the values TRUE
,
FALSE
, or null
. By contrast, a variable of type
@NonNull Boolean
always has one of the values TRUE
,
or FALSE
— never null
. Dereferencing an
expression of type @NonNull Boolean
can never cause a null pointer
exception.
The plugin issues a warning in two cases:
@NonNull
type is dereferenced,
because it might cause a null pointer exception
@NonNull
might become
null
, because it is a misuse of the type
This example shows both sorts of problems:
Object obj; // might be null @NonNull Object nnobj; // never null ... nnobj.toString() // checker warning: dereference might cause null pointer exception nnobj = obj; // checker warning: nnobj may become null
Parameter passing and return values are checked analogously to assignments.
In order to reduce the burden of annotating types in your program with
@NonNull
(or adding casts and new declarations to your
program), the plugin infers non-null types for some variables and
expressions, and treats them that way even when you have not annotated
them. These implicitly non-null types permit deferences, and assignments
to explicitly non-null types, without compiler warnings.
For example, consider this code. Note that the same expression may yield a warning or not depending on its context.
// Requires an argument of type @NonNull String
void parse(@NonNull String toParse) { ... }
void lex(String toLex) {
String s; // s does NOT have a @NonNull type
...
parse(s); // warning: s might be null
...
if (s != null) {
parse(s); // no warning: s is known to be non-null
}
...
parse(s); // warning: s might be null
...
s = new String(...);
parse(s); // no warning: s is known to be non-null
}
Flow-sensitive non-null inference has been implemented for the following varieties of expressions:
if
/else
statements assert
statementsreturn
or thrown exception,
or call System.exit
new
class/array expressionsNote: The items in the above list exclude complex null checks, i.e., not of the
form x != null
. Support for these types of checks will be
available in a future release.
Non-null inference is never performed for method parameters of non-private
methods and for non-private fields, because unknown client code could use
them in arbitrary ways. The inferred information is never written to the
.class
file as user-written annotations are.
The inference indicates when an un-annotated type can be treated as a
@NonNull
one. An expression of @NonNull
type is
never inferred to be treated as non-null; any such use is an error, and the
checker issues a warning.
To try the @NonNull
plugin on a source file that uses
the @NonNull
qualifier, use the following command (where
javac
is the JSR 308 compiler):
javac -typeprocessor checkers.nonnull.NonnullChecker examples/NonNullExample.java
Compilation will complete without warnings.
To see the checker warn about incorrect usage of annotations (and therefore the possibility of a null pointer exception at run time), use the following command:
javac -typeprocessor checkers.nonnull.NonnullChecker examples/NonNullExampleWithWarnings.java
The compiler will issue three warnings regarding violation of the
semantics of @NonNull
in the
NonNullExampleWithWarnings.java
file.
In addition to the tiny examples distributed with the checker,
you can also run the nonnull checker on the annotation scene library, a
larger library that has been fully annotated with @NonNull
. To
run the
nonnull checker on the annotation scene library, first download the
scene
library suite (which includes build dependencies for the scene
library as well as its source code) and extract it into your checkers
installation. The checker can then be run on the annotation scene
library with Apache Ant using the following commands:
cd $CHECKERS
ant -f scene-lib-test.xml
where $CHECKERS
is the location of the checkers
installation.
You can view the annotated source code, which contains
@NonNull
annotations, in the
checkers/scene-lib-test/src/annotations/
directory.
The plugin prevents null pointer errors in your code. In addition to the caveats for any checker, there are two additional caveats:
assert x !=
null; ... x.f ...
. If the JVM
is run with assertions disabled, then a null pointer exception could
occur. (Thus, writing an assertion is a way to suppress warnings in
the NonNull checker.)
If you have any problem with the
@NonNull
checker, please see “How to report
bugs” for information on reporting bugs, so that we can improve
it in a future release.
The @NonNull
annotation described in this document is similar,
but not identical, to the
@NotNull
annotation of IntelliJ IDEA, the
@NonNull
annotation of FindBugs,
the non_null
modifier of JML,
and annotations proposed by
JSR
305, among others.
Back to the JSR 308 checkers framework.