Using == operator in Java to compare wrapper objects
The key to the answer is called object interning. Java interns small numbers (less than 128), so all instances of Integer(n)
with n
in the interned range are the same. Numbers greater than or equal to 128 are not interned, hence Integer(1000)
objects are not equal to each other.
Comparing wrapper class with primitive using equals() gives strange behavior
longWrapper.equals(0)
returns false
, because 0
is autoboxed to Integer
, not to Long
. Since the two types are different, .equals()
returns false
.
In the meantime, longWrapper == 0
is true
, because the longwrapper
value is unboxed to 0
, and 0 == 0
without considering the actual primitive types.
Comparing two Integer Wrapper classes
Using the new
keyword always creates two different instances. So the following is always true:
new Integer(10) != new Integer(10)
hence the first line printing "false".
Then:
i++;
hides the unboxing and boxing. It is equivalent to:
i = Integer.valueOf(i.intValue() + 1);
As described in the Javadoc of Integer.valueOf
, values from -128 to 127 (at least) are cached: you are getting back the cached instance of Integer.valueOf(11)
for both i++
and i1++
, hence the second line printing "true".
operator == differet behaviour on wrapper class object
The ==
comparator checks for object equality!
Since Integer.valueOf
maintains a cache of Integer Objects with the value -128 to 127 valueOf(String)
returns the cached object, thus the ==
comparance results in true.
Integer a1 = new Integer("12");
Integer b1 = new Integer("12");
//a1 == b1 returns false because they point to two different Integer objects
Integer aa = Integer.valueOf("12");
Integer bb = Integer.valueOf("12");
//aa == bb returns true because they point to same cached object
For the comparance of object values always use the .equals
method, for primitives like int, long etc. you can use the ==
comparator.
Why can I test inequality of Wrappers like primitives? Can I do it for classes I create?
First of all - a whole ratsnest of implications has been unveiled.
What is happening is that for the operators '>=', '<=', '<', and '>' the compiler already knows that they can only be executed on primitive types, so automatically an unboxing will happen (convert the Object type to a primitive type). That is why those operators can be executed on Integer instances.
However, when using '==' or '!=', the compiler knows it can compare instances directly, basically comparing wether or not two variables are referencing the same object or not. It is not a true integer comparison at all.
As a matter of fact, this will return false:
System.out.println("Test == :"+(new Integer(1000) == new Integer(1000)));
System.out.println("Test == :"+(new Integer(100) == new Integer(100)));
These most likely will return false:
System.out.println("Test == :"+((Integer)1000 == (Integer)1000));
System.out.println("Test == :"+(Integer.valueOf(1000) == Integer.valueOf(1000)));
Although these most likely will return true:
System.out.println("Test == :"+((Integer)100 == (Integer)100));
System.out.println("Test == :"+(Integer.valueOf(100) == Integer.valueOf(100)));
'Most likely' because it is going to be implementation specific, and even can be controlled by parameters.
due to the fact that integer objects with values in the range -127..128 are being interned when using the Integer.valueOf(int)
static factory method. See a more elaborate explenation.
But please never assume that this will ever work, and always use the Comparable
interface, .equals(...)
, or do the unboxing.
For reference, also review these articles:
- Why aren't Integers cached in Java?
- Using == operator in Java to compare wrapper objects
Comparing primitive to wrapper object with == behaviour unexplained
c
and cy
refer to different instances of the Character
class (each time you invoke a constructor, you create a new instance), so comparing these references returns false
.
On the other hand, when you compare either of them to the primitive cx
, they are unboxed to char
, and the char
comparison returns true.
Had you used Character.valueOf('a')
instead of new Character('a')
, you would have gotten the same instance in both calls, and the reference comparison would have returned true
(since valueOf
returns a cached Character
instance if the argument <= 127).
Why does '', ' ' work with wrapper classes while '==' doesn't ?
The <
, >
, <=
and >=
operators are only defined for primitive types. Therefore using them on wrapper types causes the compiler to unbox the objects into primitives.
This means
System.out.println(a>=b);
is equivalent to
System.out.println(a.intValue()>=b.intValue());
However, the ==
and !=
operators exist for both primitive types and reference types, so using them to compare two objects of primitive wrapper types compares the references instead of the primitive values they wrap.
As Holger commented, comparison of object references with ==
and !=
existed in the Java language before auto-boxing and auto-unboxing were introduced, but comparison with <
, >
, <=
and >=
was not supported for any reference types before auto-unboxing was introduced.
This means that in the early days of Java, the a>=b
of your code snippet would not pass compilation (since a
and b
are not primitive numeric types). On the other hand your a==b
snippet would still pass compilation and return false
.
Changing the behavior of ==
and !=
for reference types that happen to be wrappers of numeric primitives would change the behavior of existing code, thus breaking backwards compatibility, which is probably the reason it wasn't done.
Primitive wrappers comparison
Does on the 1st line of code we make implicit boxing?
Yes
2) Why the 3rd and 6th lines of code give us different results?
Integer.valueOf(int)
pools all values from -128 to 127.
The reason is that small Integer values are used frequently and there is no point in creating a new object for all such values everytime we need an object. Hence, these are created as "interned" objects and all the references to such integer values will point to the same memory address.
code snippet from Integer.java:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
Instead, when you call new Integer(10);
, it is making an entire new object hence two different objects with same integer values will point to different memory addresses
Related Topics
Why Shouldn't You Extend Jframe and Other Components
How to Check If Multiplying Two Numbers in Java Will Cause an Overflow
Dynamic Graphics Object Painting
Changing the Shapes of Points in Scatter Plot
Jdk Dateformatter Parsing Dayofweek in German Locale, Java8 VS Java9
Migration from Struts 1 to Struts 2
How to Display Legend for Pie Chart in Columns
Change Background Color of One Cell in Jtable
Autocomplete with Java , Redis, Elastic Search , Mongo
How to Setsize of Image Using Rescaleop
Why Use a Reentrantlock If One Can Use Synchronized(This)
Jax-Rs - How to Return JSON and Http Status Code Together
How to Extract Cn from X509Certificate in Java
How to Schedule a Task to Run at Periodic Intervals
Default Values and Initialization in Java