[SOLVED] NullPointerException – How to fix it?

[SOLVED] NullPointerException – How to fix it?

Today I am going to explain to you the exception known to every Java programmer, namely NullPointerException. I hope that once you get to the end of the article, it will become clear to you why this exception is so special.

A few words about the hierarchy of exceptions in Java

NullPointerException is a kind of Java RuntimeException, which makes it belong to the unchecked exceptions group. Unlike the exceptions that inherit directly from the Exception class (called checked exceptions), there is no need to explicitly handle it in any place where it can occur. Unchecked exceptions have been marked in red in the following diagram of Java exceptions hierarchy.

Hierarchy of exceptions in Java

NullPointerException has become a subject of many publications about the code quality. The result of this fact is the creation of appropriate coding standards, as well as static code analysis rules that allow to catch potential places of its occurrence. This problem is also taken very seriously during designing new programming languages. A relatively recent example of such language is Kotlin, in which the problem of NullPointexException was practically eliminated. So, why is NullPointerException so special to pay so much attention to it?

The cause of NullPointerException

To better understand the cause of the problem, let’s look at the process of declaring variables. Variables in Java can be divided into two groups – simple and object types. Before we go any further, let’s take a look at the code below.

public class NpeVariableTest {
    public static void main(String[] args) {
        int simpleVar = 10;
        Integer objectVar1 = new Integer(15);
        Integer objectVar2 = null;

        System.out.println("simpleVar:" + simpleVar);
        System.out.println("objectVar1:" + objectVar1.toString());
        System.out.println("objectVar2:" + objectVar2.toString());
    }
}

The listing presents a declaration of a simple type variable named simpleVar, which was assigned the value 10. Additionally, we can also see the declaration of two object-type variables – objectVar1, and objectVar2. Let’s stop for a moment and think about what exactly are the two types of variables?

Variables and memory

In the case of a simple variable, the value 10 is put directly in the memory allocatoed for the variable. In the case of variables of the object type, the address (reference) of the memory area in which the object is located is stored in the variable. If you assign null to a variable, it means that the variable does not point to any object.

The direct cause of NullPointerException

We have already learned about the difference between a simple and an object types, so we are ready to go back to our example and find out what is behind the genesis of the NullPointerException.

public class NpeVariableTest {
    public static void main(String[] args) {
        int simpleVar = 10;
        Integer objectVar1 = new Integer(15);
        Integer objectVar2 = null;

        System.out.println("simpleVar:" + simpleVar);
        System.out.println("objectVar1:" + objectVar1.toString());
        System.out.println("objectVar2:" + objectVar2.toString());
    }
}

First, we declare three variables and then display their value to the standard output. After running this code, we’ll get the NullPointerException exception on the 9th line. Why? Because we tried to execute a method on an object variable that pointed to null (nothing). This is the simplest and the only direct cause of the NullPointerException exception.

Examples of constructions causing the NullPointerException

The listing below presents the declaration of the simple type simpleVar, which was number 10 assigned. Additionally, we can also see the declaration of two object-type variables – objectVar1, and objectVar2. Let’s stop for a moment and think about what exactly are the two types of variables?

public class NpeConstTest {
    private static String LASTNAME = "CIESLA";

    public static void main(String[] args) {
        String name = null;

        if (name.equals(LASTNAME)) {
            System.out.println("Hello Lukasz");
        }

        if (name.equals("SMITH")) {
            System.out.println("Hello John");
        }
    }
}

Comparison of variables to constants

One of the most common and the simplest to correct errors is a comparison of variables to constants. It usually looks like below:

if (variable.equals("CONST"))

If the value of variable is null, then we get a NullPointerException. So how can you improve this statement? Well, all you need to do is change the order, so that the constant is compared to the variable. Thanks to this simple soluton , the condition is false if the variable is null, which probably coincides with the author’s intention and it is resistant to NPE.

if ("CONST".equals(variable))

A safe version of the code is presented below.

public class NpeConstTestFixed {
    private static String LASTNAME = "CIESLA";

    public static void main(String[] args) {
        String name = null;

        if (LASTNAME.equals(name)) {
            System.out.println("Hello Lukasz");
        }

        if ("SMITH".equals(name)) {
            System.out.println("Hello John");
        }
    }
}

Type unboxing

Quite non-obvious construction that can lead to the occurrence of NullPointerException is unboxing. It is an automatic unpacking of the object type into the corresponding simple type, eg Integer on int. The following listing contains an example in which we will receive NPE in line 8. Let us then follow the mechanism of its occurrence.

public class NpeUnboxingTest {
    
    private static Integer getInteger() {
        return null;
    }

    public static void main(String[] args) {
        int simpleVar = getInteger();
        System.out.println("simpleVar:" + simpleVar);
    }
}

The getInteger() method returns an Integer object (in our example, always null). In the 8th line, the getInteger() method is called and then the return value is unboxed to the simple int type. During unboxing null value, a NullPointerException exception is thrown.

An interesting variation leading to a dangerous code is the combination of unboxing with a conditional expression. In the listing below, the object result of the getMaxAge() method is compared to a constant (30). If the method returns null then NullointerException is thrown. So how can you avoid it?

public class NpeUnboxingCondTest {
    private static Integer getMaxAge() {
        return null;
    }

    public static void main(String[] args) {
        if (getMaxAge() == 30) {
            System.out.println("You are 30");
        }
    }
}

In this particular case, it will be enough to create Integer constant and compare it to the result of the method.

public class NpeUnboxingCondTestFixed {
    public static final Integer SPECIAL_AGE = 30;

    private static Integer getMaxAge() {
        return null;
    }

    public static void main(String[] args) {
        if (SPECIAL_AGE.equals(getMaxAge())) {
            System.out.println("You are 30");
        }
    }
}

Operations on objects returned by find methods

Finding for an object and performing some operation on it is a quite frequent case which programmers have to do with. The following program silulates described case. After running the program, a NullPointerException is thrown in the 8th line, because we try to do the toString() method on a variable that does not point to any object.

public class NpeFindTest {
    private static Object findObject() {
        return null;
    }

    public static void main(String[] args) {
        Object o = findObject();
        System.out.println("I'm: " + o.toString());
    }
}

The above example is very similar to the one discussed earlier (in the unboxing section). I decided, however, to devote a separate point to it, because the problem itself was so frequent and problematic that it had an elegant solution.

The simplest solution is, of course, to check whether the findObject() method returned an object and only then performed the proper operation on it.

public class NpeFindTestFixed {
    private static Object findObject() {
        return null;
    }

    public static void main(String[] args) {
        Object o = findObject();
        if (o != null) {
            System.out.println("I'm: " + o.toString());
        }
    }
}

Although the presented solution protects against throwing an exception, it reduces the readability of the code. I mean that we write “if the value of the variable is different than null” and we read “if the object exists, then do …”. Why not to write down our intention directly?

We have an elegant tool available (Java 8 or newer), which is on of the best for this type of cases. I mean – Optional. Below is presented the code in which Optional was combined with lambda expressions also introduced in JDK 8. This construction significantly shortens the record while improving readability and protecting against NullPointerException.

public class NpeFindTestOptionalFixed {
    private static Optional<Object> findObject() {
        return Optional.ofNullable(null);
    }

    public static void main(String[] args) {
        findObject().ifPresent(object -> System.out.println("I'm: " + object.toString()));
    }
}

Initialization of object array

The last example that I decided to discuss is the incorrect initialization of tables in Java, which may result in receiving the NPE exception. Let’s see the following example.

public class NpeArrayTest {
    private static class Car {
        public void drive() {
            System.out.println("Brumm....");
        }
    }

    public static void main(String[] args) {
        Car[] cars = new Car[5];
        cars[0].drive();
    }
}

After running the program a NullPointerException is thrown in the 10th line. This is due to the fact that in the 9th line we declared a table in which we can store 5 cars. It is not the same as creating 5 cars. After this declaration, all references are set to null. In order to fill this array with cars, you have to iterate, create and assigning a car to each of the elements. Below is an fixed code that correctly initializes the array of objects.

public class NpeArrayTestFixed {
    private static class Car {
        public void drive() {
            System.out.println("Brumm....");
        }
    }

    public static void main(String[] args) {
        Car[] cars = new Car[5];
        for (int i = 0; i < cars.length; i++) {
            cars[i] = new Car();
        }
        cars[0].drive();
    }
}

If you think this post is valuable, please leave me +1 or just share it.
Your action helps me to reach a wider audience.
Thank You in advance.

Leave a Reply

avatar
  Subscribe  
Notify of
Close Menu