Let’s be honest. Dealing with null pointers in Java—most of the time—is a real pain. In fact, you can’t call yourself a Java programmer until you’ve seen the true ugliness of NullPointerException.
What makes a null pointer exception very hard to deal with is that it is a runtime exception (a subclass of RuntimeException), and not a checked exception, which is subject to a Catch or Specify Requirement. Hence, a null pointer exception will only be detected at runtime. NullPointerException arises in a number of situations: calling an instance method of an object that’s null, accessing fields of a null object, and throwing a null. Essentially, you get a NullPointerException when a null is used in places where an object is expected.
Ideally, a null pointer exception should be dealt with before runtime as it may crash a program and prevent the program from proceeding. However, explicitly writing code to check for all NullPointerException situations is not fun—in any way. (Trust me.) Long-nested if-clauses to check for null pointers make code really ugly. Java SE 8 provides no type of checking framework to deal with null pointers, so many turn to third-party solutions like Checker Framework and Eradicate for type checking. However, Java SE 8’s generic Optional class (java.util.Optional
Optional In Action
public class Test { private static class Node { Object data; Node nextNode; public Node(Object data) { this.data = data; this.nextNode = nextNode; } public void getData() {System.out.println("Data: " + data);} public void setNextNode(Node next) {nextNode = next;} } public static void main(String[] args) { Node first = new Node("first"); System.out.println(first.nextNode.getData()); } }
This piece of code will fail for one reason: We tried to dereference a null. This results in a NullPointerException, as pointed out earlier. Note that the nextNode is null. It should have been set via the setNextNode method to prevent a null pointer exception.
Using Java SE 8’s Optional class, the null can safely be dealt with. The Optional class is a generic class that serves as a container for both null and non-null values. It provides methods that allow you to safely work with values that are likely to be null and cause errors. Here’s a rewritten version of the code above, utilizing the Optional class:
import java.util.*; public class Test { private static class Node { Object data; Node nextNode; public Node(Object data) { this.data = data; this.nextNode = nextNode; } public void getData() {System.out.println("Data: " + data);} public void setNextNode(Node next) {nextNode = next;} } public static void main(String[] args) { Node first = new Node("first"); OptionalopFirst = Optional.ofNullable(first.nextNode); opFirst.ifPresent(Node::getData); } }
There are several things to note here. The ofNullable method indicates the given value can—safely!—be assigned null. In that case, an empty Optional is returned. This ensures you don’t get a null pointer exception when later working with the Optional object. This example is somewhat trivial, but gets the point across. The Optional class provides several other useful methods like flatMap, orElse, orElseGet, and ifPresentOrElse. You need some knowledge of Functional Interfaces to work with some of Optional’s methods.
Uber’s Solution to Null Pointer Exception
Null pointer exceptions exist everywhere, even at Uber. Null pointer exceptions were, in the past, a major source of crashes in the Uber Android app. For this reason, Uber developed NullAway, an open source type-based null pointer checker for Java, as third-party frameworks lacked some needed features.
With NullAway, there is little overhead added to build time (less than 10%, according to Uber). NullAway gives faster feedback when compared with other null pointer checkers, allowing you to mitigate problems before they adversely affect other program parts. NullAway is built as a plugin to ErrorProne.
Using NullAway is quite simple: Use annotations for type checking. Adding @Nullable to a return value, field, or parameter indicates that the value may be null. The @NonNull indicates a return value, field, or parameter shouldn’t be null.
Setting up NullAway can be a little tricky. (Check out the NullAway GitHub project for more instructions on setup and usage.)
Null pointer exceptions cannot be completely eradicated, as null will be needed at some point in Java code. However, it should be eliminated wherever possible. The Optional class provides a means of dealing with null pointers; however, this is not a foolproof solution. NullAway also provides a solution, which does help to some extent. Hopefully, with this information, a NullPointerException will be a pain no more.