It was very confusing to me to observe this situation:
Integer i = null;
String str = null;
if (i == null) { //Nothing happens
...
}
if (str == null) { //Nothing happens
}
if (i == 0) { //NullPointerException
...
}
if (str == "0") { //Nothing happens
...
}
So, as I think boxing operation is executed first (i.e. java tries to extract int value from null) and comparison operation has lower priority that’s why the exception is thrown.
The question is: why is it implemented in this way in Java? Why boxing has higher priority then comparing references? Or why didn’t they implemented verification against null before boxing?
At the moment it looks inconsistent when NullPointerException is thrown with wrapped primitives and is not thrown with true object types.
The Short Answer
The key point is this:
==between two reference types is always reference comparisonIntegerandString, you’d want to useequalsinstead==between a reference type and a numeric primitive type is always numeric comparisonnullalways throwsNullPointerExceptionString, it is in fact NOT a primitive typeThe above statements hold for any given valid Java code. With this understanding, there is no inconsistency whatsoever in the snippet you presented.
The Long Answer
Here are the relevant JLS sections:
This explains the following:
Both operands are reference types, and that’s why the
==is reference equality comparison.This also explains the following:
For
==to be numerical equality, at least one of the operand must be a numeric type:This explains:
Here’s an excerpt from Effective Java 2nd Edition, Item 49: Prefer primitives to boxed primitives:
There are places where you have no choice but to use boxed primitives, e.g. generics, but otherwise you should seriously consider if a decision to use boxed primitives is justified.
References
Integerto typeint"risnull, unboxing conversion throws aNullPointerException"==and!===and!=Related questions
Integersin Java does auto-unboxing occur?==but notequals()?Related questions
int num = Integer.getInteger("123")throwNullPointerException? (!!!)String.equalsversus==