Post

Guide to NullPointerException in Java And How to Avoid it

null in Java is used in relation to objects to indicate that a reference variable does not reference any object in memory. It simply denotes the absence of value.

We can only assign null to a reference type variable (Strings, Objects and arrays):

1
2
3
4
5
  String str = null;

  Object obj = null;

  int[] intArr = null;

When a reference points to nothing where it’s expected to, Java halts the program and throws a NullPointerException exception.

NullPointerException or NPE for short is one of the most commonly dreaded exceptions We’ll discuss why it exists and how to avoid it in detail.

When we declare a variable of a non-primitive type such as String, Class, Array, etc., Java creates an object that holds the value of that reference type, stores it on the heap and returns a reference of that object which is then stored in the variable we declared. Through that reference, we can access the object’s properties and methods.

So null can only be assigned to reference type variables and not primitives. But why?

The answer is simple, a primitive type points directly to the value stored in memory, whereas a reference type holds a reference to an object. So for example, if we declare a variable of type String and assign null to it like so:

String str = null;

we’re essentially saying that the above variable does not point to any object in memory. That’s why the concept of null only works with reference types.

What is NullPointerException in Java? Now that we have some idea about null in Java. Let’s dive deep into the main topic.

NullPointerException or NPE is a common runtime exception that occurs when you attempt to access or perform an operation on an object with a null reference. It’s a class that extends java.lang.RuntimeException, meaning it will be raised once you execute the code. Let’s see a quick example:

String str = null System.out.println(str.length()); In the above code, variable str is assigned a value of null. Then the .length() is called to get the length of the String variable, but since it’s assigned to null, a java.lang.NullPointerException will be thrown.

Exception in thread “main” java.lang.NullPointerException

There are many common scenarios where we may encounter this error. According to oracle documentation, here is a list of cases:

Calling the instance method of a null object.

String str = null; System.out.println(str.toUpperCase()); // throws NPE

Accessing or modifying the field of a null object.

class MyClass { private String name;

public void setName(String name) { this.name = name; }

public String getName() { return this.name; } }

public class Example { public static void main(String[] args) { Myclass myclass = null; // an object of MyClass assgined as null // if we attempt to modify the name myClass.setName(“java”); System.out.println(myClass); // throws NPE

1
2
3
   // if we attemp to access the name
   myClass = null;
   System.out.println(myClass.getName()); // throws NPE    }  }

Taking the length of null as if it were an array.

int[] arr = null; System.out.println(arr.length()); // throws NPE Accessing or modifying the slots of null as if it were an array.

String[] stringArr = null; stringArr[0] = “example”; // throws NPE Throwing null as if it were a Throwable value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  class MyClass {
    private String name;

    public String getName() {
      throw null;
    }
  }

  public class Example {
    public static void main(String[] args) {
      MyClass myClass = new MyClass();
      System.out.println(myClass.getName()); // throws NPE
    }
  }

Why is it important to avoid NullPointerException?

Null pointer exceptions will occur throughout the application’s life unless we make sure to take the necessary precautions to prevent them beforehand as much as possible. This is an important step in the development of an application, but why? Well, because NullPointerException can cause some pretty annoying issues. It can cause the application to crash or behave unexpectedly because NullPointerException is an unchecked runtime exception. In other words, it only occurs during runtime and causes the application to terminate abruptly. And that’s not something you want in your application.

It can be difficult to debug, especially given the fact that it occurs at runtime. Imagine having to deal with this in complex applications with interdependent components.

Prevention saves developers time and effort instead of wasting time having to stare at the logs and track the buggy line of code.

These are by no means the only reasons, but you get the idea. The more we catch errors by surprise, the more reliable and predictable our application would be, thus improving user experience and satisfaction.

How to prevent NullPointerException There are various techniques that we can use to handle NullPointerException. Let’s list down and discuss some of them:

Using simple null checks: One of the most basic techniques to prevent NPE is by adding a null check to ensure an object is null-safe before accessing it or using any of its methods. We can accomplish this in different ways:

with if-else statement: When comparing two objects, it’s always recommended to have the non-null object on the lefthand side of the .equals() method. Otherwise, the code will produce NullPointerException. This is because the .equals() method is a member method of an object, so if you try to call a method of an object that is assigned as null then you already know the outcome of doing so. Look at the code below:

1
2
3
4
5
6
7
8
9
10
  String str1 = null;
  String str2 = "Not Null";
  // this will produce NullPointerException
  if(str1.equals(str2)) {
      // do something
  }
  // this will safely pass   
  if(str2.equals(str1)) {
      // do something
  }

Let’s see another example of null check on an array

1
2
3
4
5
6
  String[] strArr = null;
  if(strArr != null) {
      // do something
  } else {
      // do something        // throws NPE
  }

with ternary operator:

String str = null; String result = str != null ? str : “Hello World!”; System.out.println(result); Using this special syntax, if str is not null then return it, otherwise, print “Hello World!”. The output of the above code will give us “Hello World!”.

java.util.Objects: Objects class is a java.util class that provides several static utility methods to work with objects. We can use a variety of those methods to handle NPE . Let’s take a look:

isNull(Object obj): returns true if the object is null, otherwise returns false.

Objects.isNull(null); // true nonNull(Object obj): returns true if the object is non-null, otherwise returns false.

Objects.nonNull(null); // false requireNonNullElse(Object obj, Object defaultObj): introduced in Java 9. It returns the first argument if it is non-null, otherwise, it returns the second argument. Keep in mind that if both arguments are null, a NullPointerExceptionwill be thrown.

String value1 = null; String defaultValue = “default value”; // returns defaultObj Objects.requireNonNullElse(value1, defaultValue); // if both arguments are null Objects.requireNonNullElse(null, null); // NPE requireNonNullElseGet(Object obj, Supplier<? extends T> supplier): takes an object and supplier function as arguments. It returns the first argument if it’s non-null, otherwise returns the value of Supplier.get() if it is non-null. If both the object and the supplier or value of Supplier.get() are null, we will be greeted by the familiar NullPointerException.

String value1 = null; String defaultValue = “default value”; // returns defaultValue Objects.requireNonNullElseGet(value1, () -> defaultValue); // if both arguments are null Objects.requireNonNullElseGet(null, () -> null); // NPE

Optional class:

Optional is a container object and one of the many features introduced in Java 8 to safely handle NPE without the need to resort to null checks. To use it, we start by first wrapping a potentially nullable value in Optional object, then use of one its methods to check whether the value is present and retrieve it if it is.

Optional value = Optional.ofNullable(“foo”); if(value.isPresent()) { System.out.println(value.get()); // returns foo } As you can see, we wrapped an Optional around a String value of foo and invoked ofNullable() static method that returns an Optional object containing that value if it’s present or else just returns an empty Optional. Let’s see more examples of Optional methods:

ofNullable(): returns an Optional containing the value if it is present, or an empty Optional if it is null.

Optional myString = Optional.ofNullable(null); empty(): returns an empty Optional object in case a value is null.

Optional value = myString.isPresent() ? myString : Optional.empty();
System.out.println(value); // returns Optional.empty orElse(Object other): works similar to ofNullable(), but returns a default specified value if the value is not present.

String defaultValue = myString.orElse(“default”); System.out.println(defaultValue); orElseGet(Supplier<? extends T> supplier): works slightly different from orElse(). If the Optional is empty, it returns a value returned by the specified supplier function.

// method to be passed by the supplier function public static String getMessage() { return “Hello World!”; } String defVal = myString.orElseGet(() -> getMessage()); System.out.println(defVal); There is another difference between orElse()and orElseGet(): orElse() always evaluates the default value regardless of whether the Optional is empty or not. orElseGet() only executes the supplier function if the Optional is empty. The difference can be more significant in cases where the default value involves expensive computations, making orElseGet() more preferable since it avoids unnecessary operations if the Optional is present.

orElseThrow(Supplier<? extends X> exceptionSupplier): if the Optional is empty, this method throws an exception returned by the specified Supplier function.

String value = myString.orElseThrow(() -> new RuntimeException(“the value is not present”)); System.out.println(value); isPresent(): returns true if the Optional contains a non-null value, or false otherwise.

System.out.println(myString.isPresent()); ifPresent(Consumer<? super T> consumer): takes a Consumer function as an argument. It uses a lambda expression or method reference to execute a specific action if the value contained within the Optional object is present, otherwise, it does nothing.

// using lambda expression myString.ifPresent(str -> System.out.println(str)); // method reference myString.ifPresent(System.out::println); Apache Commons StringUtils:

Apache Commons Lang is a third-party library that provides utility classes and methods to deal with Java objects. One of these classes is StringUtils, which contains static methods that work with Strings and can be utilized to prevent NPE. Let’s look at some of them:

isEmpty(CharSequence cs): returns true if a String is null or empty

1
2
3
StringUtils.isEmpty(null);    //true
StringUtils.isEmpty("");      //true
StringUtils.isEmpty(" ");     //false isNotEmpty(CharSequence cs): returns false if a String is null or empty

StringUtils.isNotEmpty(null); //false StringUtils.isNotEmpty(“”); //false StringUtils.isNotEmpty(“ “); //true defaultIfEmpty(String str, String defaultStr): returns the first argument if it’s non-null or not empty. Otherwise, it returns the second argument

StringUtils.defaultIfEmpty(null, “foo”); // foo StringUtils.defaultIfEmpty(“”, “foo”); // foo StringUtils.defaultIfEmpty(“ “, “foo”); // whitespace isBlank(CharSequence cs): returns true if a String is null, empty or contains only whitespace characters

StringUtils.isBlank(null); //true StringUtils.isBlank(“”); //true StringUtils.isBlank(“ “); //true isNotBlank(CharSequence cs): returns false if a String is null, empty or contains only whitespace characters

StringUtils.isNotBlank(null); //false StringUtils.isNotBlank(“”); //false StringUtils.isNotBlank(“ “); //false

defaultIfBlank(String str, String defaultStr): returns the first argument if non-null, not empty or contains whitespace. Otherwise, it returns the second argument. If both arguments are null, it just returns null.

StringUtils.defaultIfBlank(null, “foo”); // foo StringUtils.defaultIfBlank(“”, “foo”); // foo StringUtils.defaultIfBlank(“ “, “foo”); // foo In summary, NullPointerException occurs due to the existence of null concept in Java. It is important to avoid this exception to maintain a better user experience. This is made easier by a combination of Java features well as third-party libraries and the choice of which to use depends on the requirements of an application.

This post is licensed under CC BY 4.0 by the author.