Why Java does not see that Integers are equal?

2019-01-06 17:35发布

问题:

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.

回答1:

Objects (such as Integers) should not be compared through ==, but through .equals().

What's important to understand is that several different Integer objects can represent the same int value. When your program prints >>> different it simply says that the first object is not the same object as the second object. (While you probably want to compare the objects based on which value they represent.)

From the official guide on autoboxing:

[...] The == operator performs reference identity comparisons on Integer expressions and value equality comparisons on int expressions. [...]

It may be worth noting that autoboxing is guaranteed to return the same object for integral values in the range [-128, 127], but an implementation may, at its discretion, cache values outside of that range.

My general recommendation is to use int instead of Integer for all local / member variables. In this particular case you seem to store coordinates in a 2-element array. I would suggest that you encapsulate this in a Coordinates class or similar and override the equals method (and hashCode) in here.

See also

  • Introduction to autoboxing
  • Autoboxing pitfalls when comparing numbers with “==”


回答2:

If they were simple int types, it would work.

For Integer use .intValue() or compareTo(Object other) or equals(Object other) in your comparison.



回答3:

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


回答4:

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.



回答5:

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



回答6:

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.