Autoboxing and Null Pointer Exceptions
Updated 08/16/2006: Check out the discussion about this post on The Serverside.
I spent a while earlier today debugging a very small block of code that was throwing a NPE. There were few options for instances that could be null
, but since I was looking in the wrong place for the problem, it took longer than it should have to fix.
I wrapped each method call on a potentially null
object with null
checks but it was still failing, and finally I realized what was going on. I was storing int
s as values in a Map
, e.g.
Map<Integer, Integer> cycleAreas = ... for (Cycle cycle : cycles.values()) { Area area = _areaDao.create(new Area( analysis, tube, cycle, target, cycleAreas.get(cycle.getCycle()), creator)); areas.add(area); }
The exception occurred in the 3rd line, so either cycleAreas
or cycle
could be null
(not really, but I added tests anyway).
Since you can’t use a primitive as a key or value in a Map
, you just use autoboxing and use the associated non-primitive instead. But in this case the Map
might not be fully populated, so it took a few iterations to find a case where there was no area for a given cycle.
Under the hood when you autobox and treat an Integer
as an int
or vice versa, the compiler inserts a call to intValue()
or Integer.valueof()
. Since the Integer
value was null
, calling intValue()
blew up. For a more straightforward example, consider this code:
Integer z = 5; Integer i = null; int j = i;
It will fail at the last line with a NPE. It’s more obvious why if you use a decompiler on the class file:
Integer z = Integer.valueOf(5); Integer i = null; int j = i.intValue();