equality operator, odd results? [duplicate] - java

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

Related

Why == in case of Integer check for value not reference in java , case different with new operator

As we know that == in case of Objects returns true if pointing to the same reference else it returns false.
So , if i have taken
Integer a = new Integer("1"); // Creating Integer Object a
Integer b = new Integer("1"); // Creating Integer Object b
and then perform a == b , then it returns true
but they both have different references.
The JVM caches integer values between -127 to 127.
That's the reason == works for Integer value between this range.
But:
Integer i1=new Integer("11");
Integer i2=new Integer("11");
System.out.println(i1==i2); //false
Integer i3=11;
Integer i4=11;
System.out.println(i3==i4); //true
Integer i5=128;
Integer i6=128;
System.out.println(i5==i6); //false
Because it is overridden. source:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Let me more elaborate on this, #asAmit Bhati said in his answer when we write
Integer i1=new Integer("11");
Integer i2=new Integer("11");
System.out.println(i1==i2); //false
jvm creates two separate objects and comparing them with "==" results in false. but when we write the following code:
Integer i3=11;
Integer i4=11;
System.out.println(i3==i4); //true
it will be translated into this:
Integer i3=Integer.valueOf(11);
Integer i4=Integer.valueOf(11);
Implementation of valueOf method is as follow(in java 1.8):
public static Integer valueOf(int var0) {
return var0 >= -128 && var0 <= Integer.IntegerCache.high?Integer.IntegerCache.cache[var0 + 128]:new Integer(var0);
}
as you can see if the value is between -128 and Maximum cache value (which can be configured using this jvm parameter -Djava.lang.Integer.IntegerCache.high), it will retrieve the cached value and doesn't create a new instance of Integer that is why (==) returns true for certain values!
also note that the same goes for Character Wrapper class but not for Float and Double classes.
As the answer above says, it may work in many cases, nevertheless you shouldn't compare two Integer with == since it may present problems in some cases.
Check this answer for more information:
Comparing Integer values in Java, strange behavior
If you check equals method implementation in Integer class it is:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
From here you can see it uses "==" operator.
Now the reason behind it. Ultimately you have to compare value of the Integer wrapper class, which will happen automatically because of autoboxing and unboxing in Java.
And also from the method definition you can see that it is retrieving passed Object value using ((Integer)obj).intValue().

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 ==.

equals only when put into variables

I have two values to be compared. They appear to be not equal when compared directly using the == operator, but equal after they are put into local variables. Could anyone tell me why?
The code is as follows:
(MgrBean.getByName(name1).getId() == MgrBean.getByName(name2).getId()),
//This one is false,
int a = MgrBean.getByName(name1).getId();
int b = MgrBean.getByName(name2).getId();
(a == b); //This one is true.
I believe your getId() is returning an Integer instead of int.
Integer is the wrapper class for int primitive type. If you compare object reference using ==, you are comparing if they are referring to same object, instead of comparing the value inside. Hence if you are comparing two Integer objects reference, you are not comparing its integer value, you are simply checking if that two reference is pointing to same Integer object.
However, if you use a primitive type to store that value (e.g. int a = ....getId()), there is auto-unboxing happening, and that wrapper object is converted to primitive type value, and comparing primitive type values using == is comparing the value, which do the work you expect.
Suggested further reading for you:
Primitive Type vs Reference Type in Java
Auto-boxing and unboxing in Java
The most misconception about Integer type happens everywhere including other answers here
Suppose you have two integers defined as follows:
Integer i1 = 128
Integer i2 = 128
If you then execute the test (i1 == i2), the returned result is false. The reason is that the JVM maintains a pool of Integer values (similar to the one it maintains for Strings). But the pool contains only integers from -128 to 127. Creating any Integer in that range results in Java assigning those Integers from the pool, so the equivalency test works. However, for values greater than 127 and less than -128), the pool does not come into play, so the two assignments create different objects, which then fail the equivalency test and return false.
In contast, consider the following assignments:
Integer i1 = new Integer(1); // Any number in the Integer pool range
Integer i2 = new Integer(1); // Any number in the Integer pool range
Because these assignments are made using the 'new' keyword, they are new instances created, and not picked up from the pool. Hence, testing (i1== i2) on the preceding assignments returns false.
Here's some code that illustrates the Integer pool:
public class IntegerPoolTest {
public static void main(String args[]){
Integer i1 = 100;
Integer i2 = 100;
// Comparison of integers from the pool - returns true.
compareInts(i1, i2);
Integer i3 = 130;
Integer i4 = 130;
// Same comparison, but from outside the pool
// (not in the range -128 to 127)
// resulting in false.
compareInts(i3, i4);
Integer i5 = new Integer(100);
Integer i6 = new Integer(100);
// Comparison of Integers created using the 'new' keyword
// results in new instances and '==' comparison leads to false.
compareInts(i5, i6);
}
private static void compareInts(Integer i1, Integer i2){
System.out.println("Comparing Integers " +
i1 + "," + i2 + " results in: " + (i1 == i2) );
}
}

operator == differet behaviour on wrapper class object

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.

Why Java does not see that Integers are equal?

I have integers that are supposed to be equal (and I verify it by output). But in my if condition Java does not see these variables to have the same value.
I have the following code:
if (pay[0]==point[0] && pay[1]==point[1]) {
game.log.fine(">>>>>> the same");
} else {
game.log.fine(">>>>>> different");
}
game.log.fine("Compare:" + pay[0] + "," + pay[1] + " -> " + point[0] + "," + point[1]);
And it produce the following output:
FINE: >>>>>> different
FINE: Compare:: 60,145 -> 60,145
Probably I have to add that point is defined like that:
Integer[] point = new Integer[2];
and pay us taken from the loop-constructor:
for (Integer[] pay : payoffs2exchanges.keySet())
So, these two variables both have the integer type.
Check out this article: Boxed values and equality
When comparing wrapper types such as Integers, Longs or Booleans using == or !=, you're comparing them as references, not as values.
If two variables point at different objects, they will not == each other, even if the objects represent the same value.
Example: Comparing different Integer objects using == and !=.
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i == j); // false
System.out.println(i != j); // true
The solution is to compare the values using .equals()…
Example: Compare objects using .equals(…)
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i.equals(j)); // true
…or to unbox the operands explicitly.
Example: Force unboxing by casting:
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println((int) i == (int) j); // true
References / further reading
Java: Boxed values and equality
Java: Primitives vs Objects and References
Java: Wrapper Types
Java: Autoboxing and unboxing
If they were simple int types, it would work.
For Integer use .intValue() or compareTo(Object other) or equals(Object other) in your comparison.
In java numeric values within range of -128 to 127 are cached so if you try to compare
Integer i=12 ;
Integer j=12 ; // j is pointing to same object as i do.
if(i==j)
print "true";
this would work, but if you try with numbers out of the above give range they need to be compared with equals method for value comparison because "==" will check if both are same object not same value.
There are two types to distinguish here:
int, the primitive integer type which you use most of the time, but is not an object type
Integer, an object wrapper around an int which can be used to use integers in APIs that require objects
when you try to compare two objects (and an Integer is an object, not a variable) the result will always be that they're not equal,
in your case you should compare fields of the objects (in this case intValue)
try declaring int variables instead of Integer objects, it will help
The condition at
pay[0]==point[0]
expression, uses the equality operator == to compare a reference
Integer pay[0]
for equality with the a reference
Integer point[0]
In general, when primitive-type values (such as int, ...) are compared with == , the result is true if both values are identical. When references (such as Integer, String, ...) are compared with == , the result is true if both references refer to the same object in memory.
To compare the actual contents (or state information) of objects for equality, a method must be invoked.
Thus, with this
Integer[] point = new Integer[2];
expression you create a new object that has got new reference and assign it to point variable.
For example:
int a = 1;
int b = 1;
Integer c = 1;
Integer d = 1;
Integer e = new Integer(1);
To compare a with b use:
a == b
because both of them are primitive-type values.
To compare a with c use:
a == c
because of auto-boxing feature.
for compare c with e use:
c.equals(e)
because of new reference in e variable.
for compare c with d it is better and safe to use:
c.equals(d)
because of:
As you know, the == operator, applied to wrapper objects, only tests whether the objects have identical memory locations. The following comparison would therefore probably fail:
Integer a = 1000;
Integer b = 1000;
if (a == b) . . .
However, a Java implementation may, if it chooses, wrap commonly occurring values into identical objects, and thus the comparison might succeed. This ambiguity is not what you want. The remedy is to call the equals method when comparing wrapper objects.

Categories