Why can't I compare null field to a primitive [duplicate] - java

This question already has answers here:
Why comparing Integer with int can throw NullPointerException in Java?
(7 answers)
Closed 5 years ago.
Could you please tell me why I get a NullPointerException here?
public class N {
private Integer n = null;
public static void main(String... wargh) {
N obj = new N();
System.out.println(obj.n == 1);
}
}
The obj.n is (obviously!) null here, so obj.n == 1 must return false - just the same way as null == 1 returns false. But it does not. Instead, it throws an exception.

null cannot be compared to a primitive, since a primitive can never be equal to null.
null == 1 doesn't return false - it doesn't pass compilation.
Comparing an Integer to an int requires unboxing of the Integer into an int. obj.n == 1 throws NullPointException when obj.n == null, since unboxing obj.n is equivalent to executing obj.n.intValue().

Because obj.n == 1 is interpreted as primitive integer comparison, so obj.n will be auto-unboxed calling out.n.intValue(), which leads to the exception.
Formally, JLS 15.21 makes it clear that compiler knows your code is a numeric comparison, and then JLS 15.21.1 applies which states:
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
Note that binary numeric promotion performs value set conversion (§5.1.13) and may perform unboxing conversion (§5.1.8).

Related

java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" [duplicate]

This question already has answers here:
Java conditional operator ?: result type
(5 answers)
Closed 6 years ago.
I'm getting nullpointer exception if I use ternary operator.
Integer val = null;
Object res = val == null ? val : val.intValue();
But not with if else
Integer val = null;
Object res;
if( val == null ) {
res = val;
} else {
res = val.intValue();
}
Can anyone please explain why?
Thanks
Sudar
The behavior you encountered results from the rules of determining the type of the ternary conditional expression.
In your case, the type of the expression
val == null ? val : val.intValue();
is int.
This is specified by JLS 15.25. :
The type of a conditional expression is determined as follows:
If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.
Your second operand is Integer and your third operand is int, therefore the type of the expression is int.
Therefore, when val == null, val is un-boxed (i.e. val.intValue() is called for a null value) and a NullPointerException is thrown.
In your if-else expression val is not un-boxed when its value is null (since you assign it to an Object variable, so there's no NullPointerException.
That said, since you are assigning an Integer variable to an Object variable, your conditions in either of the snippets are pointless (since assigning an int to an Object variable simply boxes the int back to Integer).
You can simply assign
Object res = val;
and get the same end result without the exception.

In Java, does "==" Box or Unbox when comparing an object and a constant value? [duplicate]

This question already has answers here:
When using == for a primitive and a boxed value, is autoboxing done, or is unboxing done
(3 answers)
Is it guaranteed that new Integer(i) == i in Java?
(2 answers)
Closed 2 years ago.
When comparing an Integer object and a constant value, does Java box the value or unbox the Integer object?
Based on what I have read, "==" is a reference comparison, therefore it's only logical to assume that Java boxes the constant to perform the reference comparison between the objects. Yet, the below test code seems to be give contradictory results.
Integer v1 = 1000;
Integer v2 = 1000;
boolean b1 = v1 == 1000; //True.
boolean b2 = v1 == v2; //False. Proof that 1000 boxes to new object and is not fetched from cache.
So how does object vs constant value comparison using == works in Java? Does the operator compare by value in this case?
What you call "a constant value" is an int literal, so its type is int.
JLS 15.21.1 says:
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands.
In your v1 == 1000 test, 1000 is of numeric type and v1 is convertible to numeric type, so binary numeric promotion is performed.
JLS 5.6.2 (Binary numeric promotion) says:
If any operand is of a reference type, it is subjected to unboxing conversion
Hence, the Integer operand - v1 - is unboxed to an int and a comparison of two ints is performed. Therefore the result of the comparison is true.
When you compare two reference types - v1 == v2 - no unboxing takes places, only the references are compared, as written in JLS 15.21.3:
If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.
Since 1000 is too large to be cached by the Integer cache, b1 and b2 are not referencing the same instance, and therefore the result of the comparison is false.
Integer pools are same to string pool but it caches value if integer objects in the range -128 to 127
So when you try to assign a value in this range to a wrapper object, the boxing operation will invoke Integer.valueOf method and in turn it will assign a reference to the object already in the pool.
but, if you assign a value outside this range to a wrapper reference type, Integer.valueOf will create a new Integer object for that value. And hence, comparing the reference for Integer objects having value outside this range will give you false
So in your case
Integer v1 = 1000;
Integer v2 = 1000;
boolean b1 = v1 == 1000; //True.
boolean b2 = v1 == v2; // out of range so it will false but if you use 127 instead of 1000 then it will true.
check the documentation here

Why comparing an Integer object with a primitive int throws null pointer exception when the Integer object is null in Java [duplicate]

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 comparison
More often than not, e.g. with Integer and String, you'd want to use equals instead
== between a reference type and a numeric primitive type is always numeric comparison
The reference type will be subjected to unboxing conversion
Unboxing null always throws NullPointerException
While Java has many special treatments for String, it is in fact NOT a primitive type
The 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:
JLS 15.21.3 Reference Equality Operators == and !=
If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.
This explains the following:
Integer i = null;
String str = null;
if (i == null) { // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") { // Nothing happens
}
Both operands are reference types, and that's why the == is reference equality comparison.
This also explains the following:
System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"
For == to be numerical equality, at least one of the operand must be a numeric type:
JLS 15.21.1 Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible to numeric type, binary numeric promotion is performed on the operands. If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float or double`, then a floating-point equality test is performed.
Note that binary numeric promotion performs value set conversion and unboxing conversion.
This explains:
Integer i = null;
if (i == 0) { //NullPointerException
}
Here's an excerpt from Effective Java 2nd Edition, Item 49: Prefer primitives to boxed primitives:
In summary, use primitives in preference to boxed primitive whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations.
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
JLS 4.2. Primitive Types and Values
"The numeric types are the integral types and the floating-point types."
JLS 5.1.8 Unboxing Conversion
"A type is said to be convertible to a numeric type if it is a numeric type, or it is a reference type that may be converted to a numeric type by unboxing conversion."
"Unboxing conversion converts [...] from type Integer to type int"
"If r is null, unboxing conversion throws a NullPointerException"
Java Language Guide/Autoboxing
JLS 15.21.1 Numerical Equality Operators == and !=
JLS 15.21.3 Reference Equality Operators == and !=
JLS 5.6.2 Binary Numeric Promotion
Related questions
When comparing two Integers in Java does auto-unboxing occur?
Why are these == but not equals()?
Java: What’s the difference between autoboxing and casting?
Related questions
What is the difference between an int and an Integer in Java/C#?
Is it guaranteed that new Integer(i) == i in Java? (YES!!! The box is unboxed, not other way around!)
Why does int num = Integer.getInteger("123") throw NullPointerException? (!!!)
Java noob: generics over objects only? (yes, unfortunately)
Java String.equals versus ==
Your NPE example is equivalent to this code, thanks to autoboxing:
if ( i.intValue( ) == 0 )
Hence NPE if i is null.
if (i == 0) { //NullPointerException
...
}
i is an Integer and the 0 is an int so in the what really is done is something like this
i.intValue() == 0
And this cause the nullPointer because the i is null. For String we do not have this operation, thats why is no exception there.
The makers of Java could have defined the == operator to directly act upon operands of different types, in which case given Integer I; int i; the comparison I==i; could ask the question "Does I hold a reference to an Integer whose value is i?"--a question which could be answered without difficulty even when I is null. Unfortunately, Java does not directly check whether operands of different types are equal; instead, it checks whether the language allows the type of either operand to be converted to the type of the other and--if it does--compares the converted operand to the non-converted one. Such behavior means that for variables x, y, and z with some combinations of types, it's possible to have x==y and y==z but x!=z [e.g. x=16777216f y=16777216 z=16777217]. It also means that the comparison I==i is translated as "Convert I to an int and, if that doesn't throw an exception, compare it to i."
It's because of Javas autoboxing feature. The compiler detects, that on the right hand side of the comparison you're using a primitive integer and needs to unbox the wrapper Integer value into a primitive int value as well.
Since that's not possible (it's null as you lined out) the NullPointerException is thrown.
In i == 0 Java will try to do auto-unboxing and do a numerical comparison (i.e. "is the value stored in the wrapper object referenced by i the same as the value 0?").
Since i is null the unboxing will throw a NullPointerException.
The reasoning goes like this:
The first sentence of JLS § 15.21.1 Numerical Equality Operators == and != reads like this:
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
Clearly i is convertible to a numeric type and 0 is a numeric type, so the binary numeric promotion is performed on the operands.
§ 5.6.2 Binary Numeric Promotion says (among other things):
If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed.
§ 5.1.8 Unboxing Conversion says (among other things):
If r is null, unboxing conversion throws a NullPointerException
Simply write a method and call it to avoid NullPointerException.
public static Integer getNotNullIntValue(Integer value)
{
if(value!=null)
{
return value;
}
return 0;
}

Java - How can these 2 objects equal each other?

Hi I am revising and understand the difference between equals() and '==' however this code really confuses me:
public class MyTest {
public static void main(String[] args) {
Integer w = new Integer(1);
Integer x = 1;
double z = x;
System.out.println(z == w);
}
}
How can a double object have the same reference as an Integer object in memory when using '==' ? Cannot understand this. Thank you for reading!
If you compare primitive and wrapper using == operator, then the wrapper values will be un boxed and compared with primitive value.
From JLS 15.21.1
15.21.1. Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or
one is of numeric type and the other is convertible (§5.1.8) to
numeric type, binary numeric promotion is performed on the operands
(§5.6.2).
A double is not a reference, because it is a primitive type. It is a value instead. Double would have been a reference.
When you write z == w, where z is double-typed and w is Integer-typed, the runtime definitely has to compare something. And, obviously, it has to compare things of the same kind. It will not compare the double value with the Integer reference. Instead, it will unbox the Integer and will compare the int value obtained after unboxing with the double value. Both being 1, the boolean operator will return true.
Here objects are not compared but primitive types are compared with feature of unboxing for Integer.

Why comparing Integer with int can throw NullPointerException in Java?

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 comparison
More often than not, e.g. with Integer and String, you'd want to use equals instead
== between a reference type and a numeric primitive type is always numeric comparison
The reference type will be subjected to unboxing conversion
Unboxing null always throws NullPointerException
While Java has many special treatments for String, it is in fact NOT a primitive type
The 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:
JLS 15.21.3 Reference Equality Operators == and !=
If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.
This explains the following:
Integer i = null;
String str = null;
if (i == null) { // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") { // Nothing happens
}
Both operands are reference types, and that's why the == is reference equality comparison.
This also explains the following:
System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"
For == to be numerical equality, at least one of the operand must be a numeric type:
JLS 15.21.1 Numerical Equality Operators == and !=
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible to numeric type, binary numeric promotion is performed on the operands. If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float or double`, then a floating-point equality test is performed.
Note that binary numeric promotion performs value set conversion and unboxing conversion.
This explains:
Integer i = null;
if (i == 0) { //NullPointerException
}
Here's an excerpt from Effective Java 2nd Edition, Item 49: Prefer primitives to boxed primitives:
In summary, use primitives in preference to boxed primitive whenever you have the choice. Primitive types are simpler and faster. If you must use boxed primitives, be careful! Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. When your program compares two boxed primitives with the == operator, it does an identity comparison, which is almost certainly not what you want. When your program does mixed-type computations involving boxed and unboxed primitives, it does unboxing, and when your program does unboxing, it can throw NullPointerException. Finally, when your program boxes primitive values, it can result in costly and unnecessary object creations.
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
JLS 4.2. Primitive Types and Values
"The numeric types are the integral types and the floating-point types."
JLS 5.1.8 Unboxing Conversion
"A type is said to be convertible to a numeric type if it is a numeric type, or it is a reference type that may be converted to a numeric type by unboxing conversion."
"Unboxing conversion converts [...] from type Integer to type int"
"If r is null, unboxing conversion throws a NullPointerException"
Java Language Guide/Autoboxing
JLS 15.21.1 Numerical Equality Operators == and !=
JLS 15.21.3 Reference Equality Operators == and !=
JLS 5.6.2 Binary Numeric Promotion
Related questions
When comparing two Integers in Java does auto-unboxing occur?
Why are these == but not equals()?
Java: What’s the difference between autoboxing and casting?
Related questions
What is the difference between an int and an Integer in Java/C#?
Is it guaranteed that new Integer(i) == i in Java? (YES!!! The box is unboxed, not other way around!)
Why does int num = Integer.getInteger("123") throw NullPointerException? (!!!)
Java noob: generics over objects only? (yes, unfortunately)
Java String.equals versus ==
Your NPE example is equivalent to this code, thanks to autoboxing:
if ( i.intValue( ) == 0 )
Hence NPE if i is null.
if (i == 0) { //NullPointerException
...
}
i is an Integer and the 0 is an int so in the what really is done is something like this
i.intValue() == 0
And this cause the nullPointer because the i is null. For String we do not have this operation, thats why is no exception there.
The makers of Java could have defined the == operator to directly act upon operands of different types, in which case given Integer I; int i; the comparison I==i; could ask the question "Does I hold a reference to an Integer whose value is i?"--a question which could be answered without difficulty even when I is null. Unfortunately, Java does not directly check whether operands of different types are equal; instead, it checks whether the language allows the type of either operand to be converted to the type of the other and--if it does--compares the converted operand to the non-converted one. Such behavior means that for variables x, y, and z with some combinations of types, it's possible to have x==y and y==z but x!=z [e.g. x=16777216f y=16777216 z=16777217]. It also means that the comparison I==i is translated as "Convert I to an int and, if that doesn't throw an exception, compare it to i."
It's because of Javas autoboxing feature. The compiler detects, that on the right hand side of the comparison you're using a primitive integer and needs to unbox the wrapper Integer value into a primitive int value as well.
Since that's not possible (it's null as you lined out) the NullPointerException is thrown.
In i == 0 Java will try to do auto-unboxing and do a numerical comparison (i.e. "is the value stored in the wrapper object referenced by i the same as the value 0?").
Since i is null the unboxing will throw a NullPointerException.
The reasoning goes like this:
The first sentence of JLS § 15.21.1 Numerical Equality Operators == and != reads like this:
If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
Clearly i is convertible to a numeric type and 0 is a numeric type, so the binary numeric promotion is performed on the operands.
§ 5.6.2 Binary Numeric Promotion says (among other things):
If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed.
§ 5.1.8 Unboxing Conversion says (among other things):
If r is null, unboxing conversion throws a NullPointerException
Simply write a method and call it to avoid NullPointerException.
public static Integer getNotNullIntValue(Integer value)
{
if(value!=null)
{
return value;
}
return 0;
}

Categories