Skip to content

NullPointerExceptions

I am usually logged into ##java on freenode (IRC) and in an effort not to repeat myself, I’ll write up some basic java guides here from time to time.

Today’s missive is about the NullPointerException

What does it mean

In java, objects are crucial. Almost everything is a reference to an object. For example:

    //example holds a REFERENCE to an integer object.
Integer example = new Integer(5);
   //text holds a REFERENCE to a string object.
String text = "foobar";

Thus, variables are really references. However, it’s legal for a reference to say: I’m currently not actually referencing anything. This is what ‘null’ is all about. e.g.:

    //example can hold a REFERENCE but at the moment it points to nothing.
Integer example = null;
    //text can hold a REFERENCE but at the moment it points at nothing.
String text = null;

Having ‘null’ in variables is no problem at all, but, of course, given that they don’t actually refer to anything, you can’t derefence them – you can’t manipulate the object they refer to because they don’t refer to anything.

The ways in which you can derefence an object in java follow. NullPointerExceptions occur ONLY in the following situations, and the NullPointerException is ALWAYS what you get in the following situations.

Straight dereference

String x = null;
System.out.println(x.toLowerCase()); //NPE!

The above code snippet throws a NullPointerException on the second line. The dot (.) operator in java derefences into a member of the object. In this case, we want to call the ‘toLowerCase()’ method of the object pointed at by our variable x. Except of course, x doesn’t point anywhere, so, NPE. 90%+ of all NPEs are caused by this kind of situation. Note that in theory an NPE on line 2 could also be caused by the . between “out” and “println” if ‘System.out’ is null, but normally it isn’t.

The ‘.’ can also be used to refer to a static method or field. This in fact the case for “System.out” – out is a static member of the System class. Such ‘.’ operations can never throw an NPE.

Array dereference

String[] texts = null;
System.out.println(texts[10]);  //NPE

The [10] operation refers to the 11th element in the texts array. However, texts is currently not pointing at an actual String array, it’s pointing at nothing (null). Hence trying to ‘derefence’ the array fails and throws an NPE. You can consider array lookup (the [10] part) to be analogous to something like texts.getElement(10); which obviously can generate NPEs. So can arrayName[idx].

foreach loops

List list = null;
for ( Object o : list ) doSomething(); //NPE!

The ‘foreach’ notation, introduced in java 1.5, is a shortcut that calls on the object being iterated over (‘list’ in our example) to provide a so-called Iterator. It does this simply by calling list.iterator() ‘under the hood’. As you can see by the ‘.’, this can actually throw an NPE if the object being iterator over is null, as it is in the above code sample.

interlude: primitives

So far all our variables (String text, Integer example, List list, etcetera) have all been objects. You recognize them because their type name (String, Integer, List) starts with a capital letter. There is another sort of type in java – the primitive. There are only a set number of them and you can’t make new ones: “boolean, char, byte, short, int, long, float, double” – these are the primitives.

primitives in java do not ‘refer’ to anything, they hold the value itself directly. This is very different from the ‘reference’ scheme that objects use. Consider the following code example:

List list1 = new ArrayList();
List list2 = list1;
list1.add("testing");
System.out.println(list1.size());
System.out.println(list2.size());

The above code sample will actually print ’1′, and then ’1′ AGAIN, because there’s only ONE list – the one we create with new in the first line of the code snippet. ‘list2′ is merely an alias for the same ArrayList object.

However, for primitives, the number/character/boolean is stored directly:

int number1 = 5;
int number2 = number1;
number1 = 10;
System.out.println(number1);
System.out.println(number2);

The above sample will print ’10′, but then ’5′. The int number 2 = number1; operation copied the value of number1 into number2. In this case, because we are dealing with primitives, the value ’5′ itself is copied. In the example with the List objects above, the reference to the list was copied around.

Because primitives hold a direct value and don’t refer to anything, they cannot be null. The following code makes no sense and is a compile-time syntax error:

int number = null; //This is not legal code

(NB: While this whole ‘reference’ thing can get very confusing, there’s also such a thing as an immutable – objects that cannot change state once they are constructed. Integer, Character, Boolean, and co. are all immutable (they have no set() methods or any other ways of changing the value they hold), which makes reasoning about their ‘reference’ nature trivial. Immutables are a good idea and I’ll dedicate another post to it at some point. Feel free to ask in ##java about them).

Auto-unboxing

Starting with java 1.5, the object versions of the primitives (Boolean, Character, Byte, Short, Integer, Long, Float, and Double) ‘translate’ themselves to their primitive counterparts on demand, and the same is true for the reverse. For example, a List is a collection of objects. But what if you want to have a list of integers? Before java1.5, you had to work with Integer objects. e.g. you had to pull this stunt:

List list = new ArrayList();
list.add(new Integer(20)); //fine, Integer is an object
list.add(20); //not fine - 20 is an 'int' and not an object

In java 1.5, the following happends:

List list = new ArrayList();
list.add(20); //java will convert the '20' int to an Integer object.

This act is called auto-boxing (for converting an int to an Integer in the above example). The reverse is called auto-unboxing (converting an Integer to an int, a Character to a char, etcetera).

In practice the object versions of the primitives can hold the exact same values as the primitive versions except for one detail: object references can be ‘null’ but primitive references cannot. In other words:

Integer number1 = null; //fine
int number2 = null; //compile time error

This throws a wrench in the works for auto-unboxing: You can’t auto-unbox null.

auto-unboxing occurs in 2 situations: First, when you use number operators like +, -, *, /, <<, >>, &, |, etcetera – those work only on primitives, so the object versions of the primitives auto-unbox when you use them in such calculations. Secondly, anytime a primitive is desired but you use the object version instead, auto-unboxing occurs. This works both in method parameters and for assignment.

Here are some examples: (Note that the code snippet will compile fine, just doesn’t work when you run it)

Integer number1 = null;
int number2 = 5;
int number3 = number1 + number2; //NPE!
int number4 = number1; //NPE!
callMethod(number1); //NPE!

public void callMethod(int number) { //doSomething }

Synchronizing on null

At this point we’ve reached the rare cases that you’ll basically never ever encounter as a newcomer to java. But, for completeness:

Object o = null;
synchronized ( o ) {  //NPE!
    doStuff();
}

Anytime the argument to ‘synchronized’ is null, an NPE follows. synchronized is used to keep multiple threads from causing errant conditions. It’s a topic worthy of its own article, so I won’t cover it further here.

Throwing null

Normally, you’ll always create exceptions in the same line you throw them, but this is not a requirement. See this snippet:

RuntimeException e = null;
throw e;  //NPE!

Technically legal and will throw a NullPointerException instead of whatever you were expecting. Not creating the exception as you throw it (like so:)

throw new RuntimeException("Testing");

is rare and usually reserved for ‘re-throwing’, in which case you probably got the exception by catching it, which means it is guaranteed to hold a real value and not ‘null’. To summarize, this particular source of NPEs is even more rare than synchronizing on null.

And that’s it – these are the ONLY TIMES a NullPointerException can occur.

{ 5 } Comments

  1. Cristiano | 2006/11/21 at 21:19 | Permalink

    I forwarded this to all my first year students, just to brighten up there memory :D

  2. Anonymouse | 2006/11/26 at 09:49 | Permalink

    This article is wrong, there are other times that a NullPointerException can occur.

  3. rzwitserloot | 2006/11/26 at 17:31 | Permalink

    Spill, then, if you’re so sure.

  4. Anonymouse | 2006/11/26 at 20:49 | Permalink

    Here are a couple – there are more.

    Object o = null;
    synchronized(o) {

    }

    Throwable t = null;
    throw t;

  5. rzwitserloot | 2006/11/27 at 02:27 | Permalink

    Added those two.