Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
The goal of this tutorial is to learn how to use the Checker Framework, and specifically the Nullness Checker in a real-world project.
Ideally, once we’re done we can be sure that our code is safe from
The Nullness Checker
The Nullness Checker’s promise is that once it
issues no warnings for a given program, then running that program will never throw a null pointer exception.
To keep that promise it needs a little help from us, the programmer. We need to
make some of our knowledge of nullness in the program explicit by annotating
types as either
As an illustration, the signature of
makeSlug from the introduction is really
public static @NonNull String makeSlug(@NonNull String s)
and the signature of
getTitle, if it might return
null, is properly
public @Nullable String getTitle()
In a sense, these annotations are like an additional, refined type system placed
on top of the Java one. Something that has a type that includes the
(the result of
@Nullable String) is obviously not compatible with
a type that cannot hold a
null value (the parameter of
@NonNull String). We can think of these annotations as constituting a pluggable type
system. The Nullness Checker’s job is to make sure our program is type-safe
with respect to this nullness type system.
Now, it would be pretty tedious if we had to annotate every reference as either
@NonNull. As a convenience, the Nullness Checker makes a
reasonable assumption about the types of references: every unannotated reference
is assumed to be
@NonNull by default.
Just to make sure we’re on the same page, a quick word on why this assumption makes sense: let’s talk about null-safe programming practice.
The first rule of null-safe programming is don’t use
Simply put, if you don’t use
null you won’t get
that doesn’t need to deal with null references is not only safer, but also more
concise. Others have explained this
number of strategies exist to avoid using null, such as using null-objects
instead, returning empty collections or
null, failing fast when receiving
null arguments, and insisting
on limiting the scope of nullable references where they cannot be avoided. Check
the References for more on this topic.
If avoidance of
null is our goal and guiding principle, then we can sensibly
assume that all references are not
null by default. The case that we want to
stand out in code is really the nullable reference. That’s where we must be on
our toes and guard against attempts to dereference it.
Helpfully, the Nullness Checker shares this attitude towards nullability. In the
eyes of the Nullness Checker, every type use carries an implicit
annotation. It’s the nullable references that need to be marked up as
@Nullable – and that is what we are going to do.
The Pet Clinic
Enough theory, let’s get started.
Our mission is to learn how to use the Nullness Checker, and we’re going to learn this by integrating it into a real-world (work with me) project.
The Pet Clinic isn’t a project anybody will be passionate about, but it has some characteristics that make it a good choice.
- The Pet Clinic has some typical enterprisey bits to it which many programmers must (for better or worse) work with every day.
- The Pet Clinic is a typical legacy software project. There’s bound to be some shoddy code in there and that’s for the Checker Framework to chew into.
- At 1600 lines of code it is just the right size.
Ok, on to checking out the code and setting up the project on the next page.