I ran across a very weird NPE this morning, and reduced it to a simple example. Is this a JVM bug or correct behavior?
public class Test1 {
class Item {
item may not be null, but when you call getId(), that is returning null. When you try to auto-unbox null, you get an NPE.
The type of the expression item == null ? 1 : item.getId() is int not Integer. Therefore, Java needs to auto-unbox your Integer to an int (causing the NullPointerException). Then it auto-boxes the result back to an Integer (well it would if not for the NullPointerException) to return from the method.
On the other hand, the expression item == null ? new Integer(1) : item.getId() has a type of Integer and no auto-unboxing needs to be done.
When you auto-unbox a null Integer, you get a NullPointerException (see Autoboxing) and that is what you are experiencing.
To answer your question, this is correct behavior.
The return type below is Integer -
public Integer f() {
Item item = new Item();
// this works:
//return item == null ? new Integer(1) : item.getId();
// NPE??
return item == null ? 1 : item.getId();
}
And the result of the following -
item == null ? 1 : item.getId()
is null in your case.
So, JVM is throwing NPE because it is trying to autobox null.
Try -
new Integer(null); // and
Integer.valueOf(null);
both will throw NPE.
It happens because you are using conditional operator ?. Line
return item == null ? 1 : item.getId();
is equivalent to
int result = item == null ? 1 : item.getId();
return result;
The result is int because of the first operand in your expression. This is the reason that your code works when you explicitly wrap 1 with Integer. In this case the compiler creates something like
Integer result = item == null ? new Integer(1) : item.getId();
return result;
So, NPE happens when attempting to "cast" item.getId() (that is null) to int.
If you decompile the class file you will see clearly your NPE...
return Integer.valueOf(item != null ? item.getId().intValue() : 1);