NullPointerException
is a common exception in Java-based applications. It is also known as Billion-Dollar mistake. NullPointerException
is a sub-class of RuntimeException
.
A RuntimeException is an unchecked exception, it does not force you to use catch block to handle it. This article going to explain some approaches to handle NullPointerException
effectively.
Why NullPointerException occur in your code
Before looking into approaches, let’s get to know why NullPointerException
happens.
NullPointerException
is thrown when an application attempts to use null in a case where an object is required. These include:
- Calling the instance method of a
null
object. - Accessing or modifying the field of a
null
object. - Taking the length of
null
as if it were an array. - Accessing or modifying the slots of
null
as if it were an array. - Throwing
null
as if it were aThrowable
value.
A null
object is an object which has not been initialized yet.
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class UserServiceTest {
@Test
void whenExceptionThrown_thenAssertionSucceeds() {
String userName = null;
assertThrows(NullPointerException.class, () -> {
userName.length();
});
}
}
The above unit test method whenExceptionThrown_thenAssertionSucceeds()
is pass. The unit test expected NullPointerException
to be thrown, because of the code is accessing length()
method on a null
object.
Where normally Java NullPointerException Occurs
-
- Invoking methods on an object which is
null
or not initialized. - Using
synchronized
on an object which isnull
- Chained statements i.e. multiple method calls in a single statement
- Invoking methods on an object which is
Guides to handle NullPointerException
Solution#1 Use Java Libraries e.g. Apache Common Lang and Google Guava
Solution#2 Use ternary operator to check value. If the value is null
then assign a default value, otherwise evaluate the value.
StringUtils.isNotEmpty()
if (StringUtils.isNotEmpty(obj.getStringValue())){
String s = obj.getStringValue();
....
}
Strings.isNulllOrEmpty()
if (Strings.isNulllOrEmpty(obj.getStringValue())){
String s = obj.getStringValue();
....
}
TextUtils.isEmpty()
if (TextUtils.isEmpty(obj.getStringValue())){
String s = obj.getStringValue();
....
}
Solution#3 Always put input validation at the beginning of your method so that the rest of your code does not have to deal with the possibility of incorrect input. So if someone passes in a null
, things will break early in the stack rather than in some deeper location where the root problem will be rather difficult to identify.
Aiming for fail fast behavior is a good choice in most situations.
Solution#3 You should always put input validation at the beginning of your method so that the rest of your code does not have to deal with the possibility of incorrect input. So if someone passes in a null
, things will break early in the stack rather than in some deeper location where the root problem will be rather difficult to identify.
Solution#4 Null
problem occurs where object references points to nothing. So always use primitives as much as possible because they does not suffer with null references. All primitives must have some default values also attached so beware of it.
Solution#5 While readability of fluent interface or chained method are good, however they are not NPE friendly. A single statement spread over several lines will give you the line number of the first line in the stack trace regardless of where it occurs.
objectRef.method1().method2().method3().methods4();
These kind of chained statement will print only “NullPointerException occurred in line number xyz”. It is pain in the bug to debug such code. Please avoid such calls.
Solution#6 Use String.valueOf() Rather than toString(). Even if object is null
in String.valueOf(null) , it will not give exception and will prints ‘null
’ to output stream.
#Solution#7 In stead of writing below code for string comparison
public class SampleNPE {
public void demoEqualData(String param {
if (param.equals("check me")) {
// some code
}
}
}
write above code like this. This will not cause in NPE even if param is passed as null
.
public class SampleNPE {
public void demoEqualData(String param) {
if ("check me".equals(param)) // Do like this
{
// some code
}
}
}
Solution#8 An awesome tip to avoid NPE is to return empty strings or empty collections rather than a null
. Do this consistently across your application. You will note that a bucket load of null
checks become unneeded if you do so.
An example could be:
List data = null;
@SuppressWarnings("unchecked")
public List getDataDemo()
{
if(data == null)
return Collections.emptyLists(); //Returns unmodifiable list
return data;
}
Users of above method, even if they missed the null
check, will not see ugly NPE.