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.
Related
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).
Java operator == is used for reference comparison
then how can == be used for comparing int a =1; and int b = 1;
both values are stored in different locations then how it compares
As commented by Andy, the JLS states that the operator '==' is indeed used for reference type comparison but also for numeric type and Boolean type comparison.
int is a numeric type.
When comparing numeric types the values are compared (not the references).
However if you want to determine if the references of two integers are equal rather than the values then you can use the Integer class. This class simply wraps the primitive numeric type int.
Now consider the following code:
public class TestClass {
public static void main(String[] args)
{
Integer A = new Integer(1);
Integer B = new Integer(1);
Integer C = A;
if (A == B) System.out.println("Won't print."); // (1)
if (A.equals(B)) System.out.println("WILL Print!!!"); // (2)
if (A == C) System.out.println("WILL Print!!!"); // (3)
}
}
Because A and B are objects, the reference of A is compared to the reference of B. Even though their int values are the same, because they are independent references this statement is false.
The equals method compares the int values of each Integer object and thus is true.
Integer object C references object A. Hence this reference comparison will be true.
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 ==.
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) );
}
}
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.