This is caused by a combination of auto-unboxing, and type inference.
In both cases, it is clear from the type signature that the method must return an int
.
In your first case, you are explicitly returning null
, which is not assignable to int
, so the compiler rightly complains that this is an error.
In the second case, you're creating an anonymous value (the bit in the brackets), and so the compiler must infer the type of it. It works out that the most specific common supertype of 0
and null
is Integer
- which is correct. Therefore, your return statement is returning something of type Integer
- and this is compatible with int
, it just gets auto-unboxed at runtime. It is this auto-unboxing that throws the NPE, when the VM attempts to convert a null reference into an int
.
If it helps you to visualise it better, your second example is essentially the same as:
public int method(boolean b) {
Integer tmp = (b ? null : 0);
return tmp;
}
and so the compiler has nothing to complain about (both lines are fine on their own).
The fault here, if there is one, is with auto-unboxing, and silently pretending that Integer
is the same type as int
. It isn't, for exactly this reason.