Java NullPointerException

by Dimitris Tasios
700 views

In this article, we will learn about one of the most commonly encountered exceptions, the infamous NullPointerException in Java.

1. What Does a NullPointerException Mean in Java?

A NullPointerException, also known as NPE, is a runtime exception that occurs when we access a variable that has a null value. A null value means that the variable has no value, so it essentially means “nothing”. A null pointer exception is unchecked, so we are not obliged to handle it using a try-catch block.

2. What Are the Causes of a NullPointerException?

There are multiple scenarios that can cause a null pointer exception. Some of those are:

  1. When we call a method of a null object.
  2. Trying to access or modify the fields of a null object.
  3. When we are trying to get the length of a null array (remember that arrays are objects).
  4. Additionally, whenever we are trying to access the index of a null array.
  5. Throwing a null value or manually throwing a NullPointerException.
  6. When trying to use the synchronized keyword an a null object.

Let’s see all of those scenarios in action.

2.1 Calling a Method of a Null Object

Starting with one of the most common scenarios, here we are trying to access a method of a null object. In the following example, we are assigning null to a String, since String is an Object. Then, when we try to call the built-in toLowerCase() method, we get a null pointer exception.

At this point, it should be noted that we cannot assign a null to a primitive type, like int or double. However, we can assign null at the primitive’s wrapper classes (Integer, Double and so on).

import java.util.Locale;

public class CallMethodOfNullObjectClass {
    public static void main(String[] args) {
        // String is an object; it works similarly to all objects, including custom-made classes
        String nullString = null;

        // this will throw a NPE
        String nullLowercase = nullString.toLowerCase(Locale.ROOT);

        // we won't reach this statement
        System.out.println(nullLowercase);
    }
}

The output is:

Exception in thread "main" java.lang.NullPointerException
        at CallMethodOfNullObjectClass.main(CallMethodOfNullObjectClass.java:9)

2.2 Accessing or Modifying the Fields of a Null Object

In this scenario, we have a null object and we are trying to either access or modify one of its fields.

In this example, we have made a very simple class named Person which has a single field. If we create a null object of this class and try to access the name field, we will get a null pointer exception.

public class AccessModifyFieldOfNullObjectClass {
    public static void main(String[] args) {
        // create a null object of custom-made class
        Person nullPerson = null;

        // accessing the name variable will throw a NPE
        String nullPersonName = nullPerson.name;

        // this will not get executed. However, you can comment out line 7 in order to get a NPE here
        nullPerson.name = "Professor Chaos";
    }
}

class Person {
    public String name;
}

The output is:

Exception in thread "main" java.lang.NullPointerException
        at AccessModifyFieldOfNullObjectClass.main(AccessModifyFieldOfNullObjectClass.java:7)

For the sake of completeness, if we were to comment out line 7 from the above example and tried to modify name, we would get a null pointer exception on line 10 instead:

Exception in thread "main" java.lang.NullPointerException
        at AccessModifyFieldOfNullObjectClass.main(AccessModifyFieldOfNullObjectClass.java:10)

2.3 Trying to Get the Length of a Null Array

Here, we have a null array and we try to access its length.

public class AccessingLengthOfNullArrayClass {
    public static void main(String args[]) {
        // a null array
        int[] nullArray = null;

        // trying to get the length of a null array results in NPE
        int nullArrayLength = nullArray.length;

        // this will not be executed
        System.out.println(nullArrayLength);
    }
}

The output is:

Exception in thread "main" java.lang.NullPointerException
        at AccessingLengthOfNullArrayClass.main(AccessingLengthOfNullArrayClass.java:7)

2.4 Accessing the Index of a Null Array

Similarly, trying to access the index of a null array will result in a null pointer exception.

public class AccessingIndexOfNullArrayClass {
    public static void main(String args[]) {
        // a null array
        int[] nullArray = null;

        // trying to access the element of a null array results in NPE
        int firstElement = nullArray[0];

        // this will not be executed
        System.out.println(firstElement);
    }
}

The output is:

Exception in thread "main" java.lang.NullPointerException
        at AccessingIndexOfNullArrayClass.main(AccessingIndexOfNullArrayClass.java:7)

2.5 Throwing a Null Value or a Null Pointer Exception Directly

Moving away from arrays, we can get a null pointer exception if we either throw a null value or throw a NullPointerException manually.

public class ThrowNullOrNPEManuallyClass {
    public static void main(String[] args) {
        throwNull();

        // this will not be executed, unless you comment out line 4
        throwNPE();
    }

    // throws a null which results in NPE
    private static void throwNull() {
        throw null;
    }

    // throws a NPE directly
    private static void throwNPE() {
        throw new NullPointerException();
    }
}

The output is:

Exception in thread "main" java.lang.NullPointerException
        at ThrowNullOrNPEManuallyClass.throwNull(ThrowNullOrNPEManuallyClass.java:11)
        at ThrowNullOrNPEManuallyClass.main(ThrowNullOrNPEManuallyClass.java:3)

Once again, by commenting out line 3, we can get a null pointer exception on line 6 instead:

Exception in thread "main" java.lang.NullPointerException
        at ThrowNullOrNPEManuallyClass.throwNPE(ThrowNullOrNPEManuallyClass.java:16)
        at ThrowNullOrNPEManuallyClass.main(ThrowNullOrNPEManuallyClass.java:6)

2.6 Using synchronized on a Null Object

Lastly, one possible scenario that causes a null pointer exception is when we try to use synchronized on an object that is null.

A synchronized object is one that can be accessed by a single thread at a time, in multithreaded applications. When an object is synchronized, only one object can access it at a time, so other threads cannot overwrite the current’s thread changes with their own.

In the following example, we have a String that we want all threads to access one at a time, so it’s placed in a synchronized block. However, the String is null so we get a null pointer exception.

public class NullSynchronizedObjectClass {
    public static void main(String[] args) {
        String nullString = null;

        synchronized (nullString) {
            System.out.println(nullString);
        }
    }
}

The output is:

Exception in thread "main" java.lang.NullPointerException
        at NullSynchronizedObjectClass.main(NullSynchronizedObjectClass.java:5)

3. How to Avoid a NullPointerException?

Now that we know how one is caused, it’s time to see how to handle a null pointer exception. In order to do that we can:

  1. Compare our object against null.
  2. Use try-catch blocks.
  3. Try to use primitive types, if possible, as they cannot be null.

3.1 Checking if an Object Is Null

The simplest thing we can do to prevent causing a null pointer exception is to check if the object is null using the == operator. If the object is null, we can then handle it however we want. One common handling of a null object (especially String) is to provide a default value through a ternary operator.

In the following example, we have a method named printCapitalized(String message) which prints a message in capital letters. Before doing so, it checks whether the message is null. If it is, then an empty string is assigned to it instead. So, in the end, if the message is empty (and by extension not null), a default message is printed instead.

public class ComparingAgainstNullClass {
    public static void main(String[] args) {
        // a null message
        String message = null;

        // we try to print it, instead we get our default message for invalid strings
        printCapitalized(message);

        // we set a message now
        message = "I like apples";

        // all good, the message is printed in capitals
        printCapitalized(message);
    }

    // prints a string in capitals, as long as it's not null or empty
    private static void printCapitalized(String message) {
        // checking for null with "== null" statement
        String messageCapitalized = (message == null) ? "" : message.toUpperCase();

        // a string that is "" can be checked with the isEmpty() method
        if(messageCapitalized.isEmpty()) {
            System.out.println("Your message is empty.");
        } else {
            System.out.println(messageCapitalized);
        }
    }
}

The output is:

Your message is empty.
I LIKE APPLES

As you can see, we used the ternary operator on line 19 to check if the message == null in one line. By doing that, the printCapitalized() method is protected from null pointer exceptions.

At this point, it should be noted that in Java 8, when dealing with lambda filtering, we can use the following statement to get the non-null elements of a collection:

.stream().filter(Objects::nonNull)

3.2 Using try-catch Blocks

Another way to handle a null pointer exception is by using try-catch blocks that have been extensively covered in our respective article. One thing to note, however, is that throwing exceptions is a very expensive operation and should only be used with care.

3.3 Using Primitives Whenever Possible

Another way to avoid running into a scenario that causes a null pointer exception is to use primitive types, like int, instead of wrapper classes, like Integer. A primitive cannot be null so it’s impossible to get a null pointer exception from there.

4. Conclusion

By now, you should be able to know everything about what causes a Null Pointer Exception in Java, as well as how to avoid and handle them, in case they do appear. You can find the source code on our GitHub page.

Related Posts