Null references have historically been a bad idea, even Tony Hoare who invented null
references calls it The Billion Dollar Mistake.
"I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object-oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years." ~ Charles Antony Richard Hoare
1. Overview
NullPointerException can sometimes be frustrating. It can break your application. It could be difficult to find an actual issue from the production server logs. In this article, I will explain what is java.lang.NullPointerException
? Also, we will see various tips and tricks that will help you in writing better code. If you already have some idea about NullPointerException, skip to the How to avoid NullPointerException? section.
2. What is NullPointerException?
The NullPointerException is a runtime exception when a program tries to access an object with a null reference. Or, does any operation on a null object. Here is a simple code snippet that throws java.lang.NullPointerException
.
Here str
is null, any operations on it will throw NullPointerException. The output if we try to run this code:
This was a trivial example, imagine if our String str
was given as an argument or in result set from a database call, the application will break. In the next section, we will see some best practices to avoid NullPointerException.
3. How to avoid NullPointerException?
One of the famous ways to avoid java.lang.NullPointerException
is to add null checks wherever plausible. However, this approach will make your code bloated with null != something
statements. Here are some best practices that you can follow to make your code NullPointerException proof.
3.1. Using Optional Class
The optional class feature was introduced in Java 8. Here is an example that explains, how you can leverage the Optional class feature to reduce NullPointerExceptions?
import java.util.Optional;
public class Example {
public static void main(String args[]) {
String str = null;
Optional<String> strOpt = Optional.ofNullable(str);
System.out.print(strOpt.orElse("").length()); // prints 0
}
}
Here, strOpt.orElse("")
gives us an empty string when str
is null otherwise it returns the original string. Below are some more useful methods that can be used with the Optional class for different scenarios:
-
public boolean isPresent()
- Returns true if there is a value present, otherwise false. -
public T get()
- If a value is present in this Optional, returns the value, otherwise throws NoSuchElementException. -
public T orElseGet(Supplier<? extends T> other)
- Returns the value if present, otherwise invoke other and return the result of that invocation.
To read more about the Optional class refer Optional (Java Platform SE 8).
3.2. Using StringUtils
StringUtils handles null
input Strings quietly. Meaning if a null String is passed it does not throw NullPointerException. It considers the null String as blank. For using this in your project you may need to import StringUtils
from Apache Commons Lang. Bellow code demonstrate the null safety feature of StringUtils.
import org.apache.commons.lang3.StringUtils;
public class Example {
public static void main(String args[]) {
String str = null;
System.out.print(StringUtils.length(str)); // prints 0
}
}
Some useful StringUtils method are as follows:
-
public static boolean isNotBlank(CharSequence cs)
- Checks if a CharSequence is not empty, not null and not whitespace only. -
public static boolean equals(CharSequence cs1, CharSequence cs2)
- Compares two CharSequences, returning true if they represent equal sequences of characters. Returns true if both arguments are null.
Read more about StringUtils here.
3.3. Using Primitive Datatypes
Since primitive datatypes can never be null. Wherever possible try using:
-
int
instead ofInteger
. -
boolean
instead ofBoolean
. -
float
instead ofFloat
. -
double
instead ofDouble
. -
long
instead ofLong
. -
short
instead ofShort
. -
char
instead ofCharacter
3.4. Calling equals on literal
While comparing two Strings or elements of an enum it is always recommended to use a non-null value at the left-hand side. Example:
public class Example {
public static void main(String args[]) {
String str = null;
if ("abc".equals(str)) {
System.out.println(true);
}
if (str.equals("abc")) // NullPointerException here
{
System.out.println(true);
}
}
}
3.5. Using Ternary Operator
Using a ternary operator you can prevent your code from throwing NullPointerExceptions, Here is how:
public class Example {
public static void main(String args[]) {
String str = null;
System.out.println(null == str ? 0 : str.length());
}
}
The above code will call length()
method only if str is not null hence preventing NullPointerException.
3.6. Throwing IllegalArgumentException
It is always a best practice to throw an IllegalArgumentException if the argument is null or something that is not expected. This may save hours of figuring out what went wrong. Here is an example code that throws IllegalArgumentException when the argument passed is null:
public class Example {
public static void main(String args[]) {
String str = null;
printStringLength(str);
}
static void printStringLength(String str) {
if (null == str) {
throw new IllegalArgumentException("String str was null");
} else {
System.out.println(str.length());
}
}
}
4. Conclusion
One of my favourite way of avoiding NullPointerException is by adding this statement null != obj.getSomething()
. But, we're mature developers we don't want to bloat our code with these null check statements, imagine a code that looks like this:
if (null != obj
&& null != obj.getSomething()
&& null != obj.getSomething().fromHere()
&& null != obj.obj.getSomething().fromHere().property()) {
// do something with obj.getSomething().fromHere().property()
}
Looks crazy right? Trust me I've written this in one of my applications to stop NullPointerExceptions. However, now we know how to avoid them in a better way.
Thank you for reading! Do let me know in the comments, what was the craziest thing you did for dealing with NullPointerExceptions.
Top comments (8)
Just adding that you can use Optional to access nested fields in a null safe way, e.g. your last code would look something like this:
Yes! Correct
I wish Java had that
?.
operator like Kotlin, TypeScript or Dart.Writing this hole expression is almost as painful as the example of the post.
Another good idea is use Null object Pattern plus the Optional, so on the orElse you return an object of the same type representing the zero value for that class. dzone.com/articles/null-object-pat...
Yes, that is cool! Thank you for your comment
Optional is not best tool, due to inconvenient API and too specific purpose. Really working universal approach is described here and it includes not only null handling. Motivation behind this approach can be found here.
great !
we should avoid ALL nulls
Null: The Billion dollar mistake
Maxi Contieri ・ Nov 18 '20 ・ 6 min read
What about lombok's @NonNull?
Don't you use/recommend it?