operator == differet behaviour on wrapper class object - java

can Any body explain me what is happeing in the output.
If == is use to compare two ref. variable it simply check its reference if they are same then it enter in if body, then why the hell
aa==bb is equal if creting static method valueOf() and ee==ff is not equal (which is ok) if creating its object using new keyword ?
static void main(String args[])
{
Integer aa = Integer.valueOf("12");
Integer bb = Integer.valueOf("12");
if(aa==bb)System.out.println("aa==bb");
if(aa!=bb)System.out.println("aa!=bb");
Integer ee = new Integer("12");
Integer ff = new Integer("12");
if(ee==ff)System.out.println("ee==ff");
if(ee!=ff)System.out.println("ee!=ff");
}
Output :
aa==bb
ee!=ff

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.

Because Integer.valueOf maintains cache of integers from -128 to 127
Here is the source code of valueOf you can clearly see that it returns same object if Integer value is between -128 to 127
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
so your == returns true. If value is more than that then it will always return you false.
Integer aa = Integer.valueOf("1200");
Integer bb = Integer.valueOf("1200");
aa == bb --> false
You should always check equality using equals method
ee.equals(ff);
If you add another if with below
if (ee.equals(ff))
System.out.println("ee equals ff");
Output will be
ee equals ff

For ee and ff two objects of Integer are created on heap hence both of them are referencing different objects so they are not equal when using == operator.

new Integer("12") creates a new Integer object with value 12. No matter how times you do that you are creating a brand new object each time. That's why == doesn't work in the second case.
The JVM maintains a cache of the Integer objects for values that are believed to be used more frequently (-128 - 127). Integer.valueOf("12") behind the scene does the same thing (new Integer("12")), but before doing that it checks in that cache if for that value the object already exists in the cache, if it does then that's what it returns, otherwise it creates a new one, adds it to the cache and returns it. That's why == works in the first case.
Also, for objects, == should never be used for equality checks, instead they should be used only for identity checks (e.g. to see if two different variables are referring to the same object). For equality check always use the equals method.

Related

Integer object caching

I read that "So when creating an object using Integer.valueOf or directly assigning a value to an Integer within the range of -128 to 127 the same object will be returned."
This is the reason why :-
Integer a=100;
Integer b=100;
if(a==b) // return true as both the objects are equal
But why not in this below case?
These two values are also in the range of 127 and -128 so according to the statement above this two will also return the same objects.
But the output here i am getting as "Not"
public static void main(String[] args) {
Integer a = 10;
Integer b = 12;
if(a == b)
System.out.println("same");
else
System.out.println("Not");
}
Can someone explain?
You're misunderstanding what "the same object will be returned" means.
So, comparison with == is actually comparing memory locations, and returns true only when the two variables hold the same object (i.e. stored at the same memory location).
Values between -128 to 127 are stored in the integer constant pool, which means that every 10 is the same 10 (i.e. the same memory location), every 12 is the same 12, etc. But it's not the case that all 10s are also 12s, which is what your question is unintentionally assuming.
Anyway, once you get outside of that range, each primitive int is a new object and is assigned to a new memory location outside of the constant pool.
You can test that with the following code:
public static void main(String[] args) {
Integer a = 1000;
Integer b = 1000;
if(a == b)
System.out.println("same");
else
System.out.println("Not");
}
That will print "Not", because a and b are two different objects stored in different memory locations.
And this is why you should compare things with .equals()
==
Checks whether both the references are pointing to the same memory location.
In the first case both values are same so they are pointing to the same location only one object will be created.
Integer a=100;
Integer b=100;
if(a==b) // return true as both the objects are equal
In the second case both values are different so they have different memory location for each so two objects will be created.
public static void main(String[] args) {
Integer a = 10;
Integer b = 12;
if(a == b)
System.out.println("same");
else
System.out.println("Not");
}
If you read the actual Java doc, you'll see a clearer description of what it is actually doing
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
As the Integer returned must represent the specified int value, there is no possible way that
Integer a = 10;
Integer b = 12;
System.out.println((a==b));
will print "true", as clearly the same object couldn't represent both values.
Edit:
For the sake of precision - The Java standard doesn't require that Integer autoboxing (assigning a primitive int to an Integer object) uses Integer.valueOf(), so it is quite possible that in a conforming Java implementation
Integer a = 10;
Integer b = 10;
System.out.println((a==b));
will print "false";
Simply They are not same object, those are two different Integer instances for to hold the given value, so as if the object are different it will always print Not

Integer caching in Java with new operator

In the below class I have tried to compare the wrapper class with the primitive but the results are different.
I have checked the following links links:
The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.
If there is a new object then how are a and c equal?
If b is equal to c and c is equal to a, then a should be equal to b. But in following case I got a != c.
Please explain.
class WrapperCompare {
public static void main (String args[]) {
Integer a = new Integer(10);
Integer b = 10;
int c=10;
System.out.println(b==c); //true
System.out.println(a==b); //false
System.out.println(a==c); //true
}
}
Update:
By referring to this link Integer caching.
Basically, the Integer class keeps a cache of Integer instances in the range of -128 to 127, and all autoboxing, literals and uses of Integer.valueOf() will return instances from that cache for the range it covers.
So in this case all statements should be true.
Explanation
When you compare Integer vs int with ==, it needs to convert the Integer to an int. This is called unboxing.
See JLS§5.1.8:
If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()
At that point, you are comparing int vs int. And primitives have no notion of instances, they all refer to the same value. As such, the result is true.
So the actual code you have is
a.intValue() == c
leading to a comparison of 10 == 10, both int values, no Integer instances anymore.
You can see that new Integer(...) indeed creates new instances, when you compare Integer vs Integer. You did that in a == b.
Note
The constructor new Integer(...) is deprecated. You should instead use Integer#valueOf, it is potentially faster and also uses an internal cache. From the documentation:
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
The caching is important to note here, since it yields to == being true again (for cached values):
Integer first = Integer.valueOf(10);
Integer second = Integer.valueOf(10);
System.out.println(first == second); // true
The caching is guaranteed for values between -128 and +127, but may also be used for others.
Also note that your b actually comes out of the cache, since
Integer b = 10;
// same as
Integer b = Integer.valueOf(10);
// and not
Integer b = new Integer(10);
So boxing goes through Integers cache (see JLS§5.1.7).

Why isn't Integer.MIN_VALUE equal to stored Integer.MIN_VALUE in variable?

I made an Interval class with the following fields:
...
private static final Integer MINF = Integer.MIN_VALUE;
Integer head,tail;
...
when I make an instance of this class, making this.head = Integer.MIN_VALUE, and I want to check if the value of head is equal to MINF, it says that they aren't equal.
Interval i = new Interval(Integer.MIN_VALUE,10);
System.out.println(i.toString()); //[-2147483648,10]
So I went ahead and tried to print the values,
public String toString() {
...
//What the hell?
System.out.println("MINF == Integer.MIN_VALUE: " + (MINF == Integer.MIN_VALUE)); //true
System.out.println("MINF == this.head: " + (MINF == this.head)); //false
System.out.println("Integer.MIN_VALUE == this.head: " + (Integer.MIN_VALUE == this.head)); //true
...
return "*insert interval in format*";
}
Which says
MINF == Integer.MIN_VALUE is true
MINF == this.head is false, although this.head = -2147483648
Integer.MIN_VALUE == this.head is true
Am I missing something for why the second one is false?
Integer is the wrapping class, child of Object and containing an int value.
If you use only the primitive type int, == does a numerical comparison and not an object address comparison.
Mind that Integer.MIN_VALUE of course is an int too.
You are missing the fact that when stored in Integer (that is, you store Integer.MIN_VALUE in two different integers) and using == between them, the comparison is not of the values, but of the objects.
The objects are not identical because they are two different objects.
When each object is compared to Integer.MIN_VALUE, since Integer.MIN_VALUE is an int, the object is autounboxed and compared using int comparison.
No one here has addressed the REASON why they're different objects. Obviously:
System.out.println(new Integer(10) == new Integer(10));
outputs false, for reasons that have been discussed to death in the other answers to this question and in Comparing Integer objects
But, why is that happening here? You don't appear to be calling new Integer. The reason is that:
Integer.MIN_VALUE returns an int, not an Integer.
You have defined MINF to be an Integer
Autoboxing uses valueOf. See Does autoboxing call valueOf()?
valueOf calls new Integer if the int is not in the integer cache,
The cache is only the values -128 -> 127 inclusive.
And that is why you are seeing the "two Integer objects are not == behavior", because of autoboxing. Autoboxing is also why equality does not appear to be transitive here.
You can fix this problem by instead using:
private static final int MINF = Integer.MIN_VALUE;
And, in general: don't use Integer for simple fields.; only use it as a generic type where you actually need the object.
You are using Integer objects. The use of == should be used as a comparison of individual primitive's values only. Since you used the Integer class rather than the primitive int then it is comparing the object's references between the two variables rather than their values.
Because MINF is a separate object to head you are receiving false for a direct comparison using ==.

what is difference between integer a = 5 and new Integer(5)?

if i write below code(in java):
Integer a =new Integer(5);
Integer b=new Integer(5);
if(a==b){
System.out.println("In ==");
}
if(a.equals(b)){
System.out.println("In equals");
}
My output is: "In equals"
But if i change first and second line to ->
Integer a =5;
Integer b=5;
then my o/p is:
In ==
In equals
So what is difference in creating a Integer object? How it gets created when we do Integer a =5?
Does it mean that a and b object refer to same object, if i create Integer a=5 and creates another object Integer b=5 ?
Integer a = 5; is called autoboxing, compiler converts this expression into actual
Integer a = Integer.valueOf(5);
For small numbers, by default -128 to 127, Integer.valueOf(int) does not create a new instance of Integer but returns a value from its cache. So here
Integer a = 5;
Integer b= 5;
a and b point to the same Object and a == b is true.
In Java, you should never use the new Integer, even though it is valid syntax it is not the best way to declare integers as you have found out. Use instead Integer.valueOf(int) This has multiple advantages.
You are not creating extra objects needlessly. Whenever you use the new operator you are forcing the vm to create a new object which is not needed in most cases. valueOf(int) will return a cached copy. Since Integer objects are immutable this works great. This means that you can use == though in practice you should use a null safe compare like in Apache ObjectUtils
The == operator tests for equality. References are only equal when they refer to the same object in memory. equals method ensures 2 object instances are 'equivalent' to each other.
Integer a = new Integer(5);
Integer b = a;
a == b; // true!
a.equals(b); // true
b = new Integer(5);
a == b; // false
a.equals(b); // true
Primitives are equal whenever their value is the same.
int a = 5; int b = a;
a == b; // true!
for primitive data types like int the equality operator will check if the variables are equal in value
for reference data types like your java.lang.Integer objects, the equality operator will check if the variables reference the same object. In the first case, you have two "new" and separate integer objects, so the references are different
Integer wrapper shares few properties of String class. In that it is immutable and that can be leveraged by using intern() like functionality.
Analyse this:
String a = "foo";
String b = "foo";
String c = new String("foo");
String d = new String("foo");
a == b //true
c == d //false
The reason is when JVM creates a new String object implicitly it reuses existing String object which has the same value "foo", as in case a and b.
In your case JVM implicitly auto-boxes the ints and re-uses existing Integer object. Integer.valueOf() can be used explicitly to re-use existing objects if available.
I believe when you create using new operator it creates object reference. In first case, there are two object references and they are not same but their value is same. That is not the situation in second case.

equality operator, odd results? [duplicate]

This question already has answers here:
How can I properly compare two Integers in Java?
(10 answers)
Closed 8 years ago.
I have a question about the following piece of code:
public class Equivalence {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}
The resulting output surprised me:
false
true
I have checked the constructor in Javadoc online, nothing help from there.
Thanks in advance
Thank you
You should use equals to check value equality. Because Integer is wrapper class which wraps int value. == checks equality based on reference so in both cases your reference is different.
Compares this object to the specified object. The result is true if and only if the argument is not null and is an Integer object that contains the same int value as this object.
n1.equals(n2);
If you do
int n1 = new Integer(47);
int n2 = new Integer(47);
You will get output you are expecting.
Because Java maintains pool of integers from 127 to -128 you can also do
Integer n1 = Integer.valueOf(47);
Integer n2 = Integer.valueOf(47);<-- will return you the same reference
n1==n2 >>> True
Only primitive types can be reliably compared with ==. For objects (and Integer is an object type), the equals() method should be used.
== can be used for objects but only to check whether two objects are in fact the same. So for example:
Integer n1 = new Integer(47);
Integer n2 = n1;
// n1 == n2 will be true
It's best if you think of ints as the number itself and Integers as a post-it note with the number written on it. == will only return true if you're talking about the same post-it note, equals() however will return true for any two notes with the same number on it.
What complicates the issue is that since version 1.5 Java also has autoboxing, that is, ints are automatically converted to Integer and vice versa when required. This can lead to very surprising results if you're not careful.
I believe it's because you're not comparing the value of n1 and n2 you're comparing the object reference. And since they are two different objects, their references are NOT the same.
Thus, you should use the equals() method to compare their values
java.Lang.Integer is an object in java. you should check if two Integer objects are equals using equals() method
you are checking if n1 reference to Integer object and n2 reference to another Integer object are referring to the same Integer Object. because == operator checks if two reference variables refer to the same object. in this case they aren't.
try
Integer n1 = New Integer(47);
Integer n2 = New Integer(47);
System.out.println(n1.equals(n2));
System.out.println(n1.equals(n2));
n1 == n2, compares the object instances and hence n1 == n2 will return false and n1 != n2 will return true as n1 and n2 are not same object instances.
If you use equals method or get int (primitive tpye) value and then compare using == or != you will get right results e.g.
System.out.println(n1.equals(n2)); //true
System.out.println(!n1.equals(n2));//false
or
System.out.println(n1.intValue() == n2.intValue()); //true
System.out.println(n1.intValue() != n2.intValue()); //false

Categories