Introduction
null is the reserved
constant used in Java to represent a void
reference i.e a pointer to nothing. Internally it is just a binary 0, but in the high
level Java language, it is a magic constant, quite distinct from zero, that
internally could have any representation.
If you write:
x.doSomething();
and x is null, you will
raise an NPE (Null Pointer Exception). Note the exception
is called NullPointerException, not
NullReferenceException even though in
theory Java has no pointers. This is a legacy term from the pre-Java Oak days.
Difference between null and an Empty Object
The difference between a null reference and a reference to an empty object, (e.g.
a freshly minted default object, empty collection or empty Iterator) is a major headache in Java. When dealing with other people’s code I want to
strangle them. Why won’t they tell me when a method might return null or empty?
Why won’t they tell me if a method can’t accept
if ( x != null )
{
x.doSomething();
}
must be the most common Java code fragment. I wish
there were some more elegant way to handle this, that gives you the speed and space
conservation of null, without the coding overhead bubblegum of checking for it at every
turn.
I have five solutions to requiring special null
handling:
- Don’t return Lists from your methods; return
Iterators instead. This way you can return the empty
Iterator. The Iterator’s
consumer does not need to deal specially with the null case. You don’t need
the overhead of cloned empty List objects.
- Create a singleton empty prototype object for each class that you pass around
to act like null. The catch is, it may actually need to be a subclass so that its
methods don’t actually do anything. You have to make sure nobody modifies the
empty object. You can safely call methods on this object and nothing will happen.
You can safely retrieve its empty/default-value fields. You would need an
amanuensis to compose the code for such objects. The effort of composing them
manually would be even more work than dealing with null. Using this technique would
be more robust however. You would make all methods final so that they would inline
down to nothing. This would be even faster than checking explicitly for null! Null
is typeless. Empty objects are typed. This may or may not be considered a Good
Thing™.
- New Java syntax to insert if (x != null) more
tersely: e.g. t!.doit(); is the same as if (t != null) t.doit();.
- Use rigid Javadoc conventions to
track whether a method consumes/produces null references, empty objects, or blank
Strings.
- Simply ignore java.lang.NullPointerExceptions. The
catch is, there is no way to do that in Java.
You can’t just ignore them and return to the code just after the call. You
can’t turn them off. This would require a new language where NullPointerExceptions are simply treated as no-ops.
Null and Garbage Collection
Obviously, if you null a reference it becomes a
candidate for GC (Garbage Collection)
sooner. In ordinary Java code, it is most common that you would exit the method
almost immediately after such a nulling, so it buys you nothing for local variables
allocated during the method invocation.
However, if you had some very complicated method, it could pay to null half-way through execution. But that being true is a symptom
that you probably would want to refactor the routine in two, which would then most
likely obviate the nulling.
Avoiding NullPointerExceptions
Here are seven techniques for
avoiding NullPointerExceptions:
- Use the @NotNulland @Nullable annotations. This does some
compile-time checking.
- Use a dummy empty object as your null
marker.
- Use the JDK (Java Development Kit) 1.8+ java.util.Optional<T>
class.
- Use the Nice language. It catches null pointers at compile time.
- Use the Groovy language. It has ?. (safe
navigation) and ?: (Elvis operator).
- Use the C# language. It has the ?? (null
coalescing operator).
- Implement the Bali language.
Learning More
Oracle’s Javadoc on
java.util.Optional class : available: