38

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.

aioobe
  • 413,195
  • 112
  • 811
  • 826
Roman
  • 124,451
  • 167
  • 349
  • 456
  • 5
    if you've got an open mind then you may like my explanation... It's because the Java creators royally screwed up when they decided to make the wrapper classes, which have really pathetic performance (you've got no idea about the waste generated by wrapping an *int* inside an *Integer*). They did this mainly because they were unable to design something clean and efficient like,say, *Trove*'s *TLongIntHashMap*. Of course expect snarky kneejerk upvoted comments here from people who drank the Java cool-aid explaining how I'm wrong and how wrapper classes are a godsend ;) – SyntaxT3rr0r Dec 13 '10 at 14:42
  • 1
    btw, never ever do a *new Integer[2]* because you force the creation of a new object. **IFF** you keep using wrapper classes like *Integer* (which you really shouldn't but that's another topic), you want to do a *Integer.valueOf(2)* (btw that later one **guarantees** as per the Java specs the reuse of the first 256 Integer objects from -128 to 127 but that is not a very well known Java brainfart). – SyntaxT3rr0r Dec 13 '10 at 14:44
  • SpoonBender: What about the Java creators' decision to *only* allow operator overloading for strings? That way `Integer.valueOf(127) == Integer.valueOf(127)` but `Integer.valueOf(128) != Integer.valueOf(128)`! – Gabe Dec 13 '10 at 15:34
  • 1
    @Gabe the problem is that Java does not have an operator for “reference comparison and I really mean it”, like the `===` of other languages. If it had, there was no problem in defining `==` as syntactic sugar for calling `equals`. Mind that, since Java 5, all the operators, `<`, `<=`, `>`, `>=`, `+`, `++`, `-`, `--`, `*`, `/`, `%`, `>>`, `<<`, `>>>`, `&`, `|`, `~`, `^` do what you would expect when applying on `Integer` objects. But the meaning of `==` and `!=`, to perform a reference comparison, couldn’t change due to backward compatibility. By the way, `+` for strings was a design mistake… – Holger Sep 20 '19 at 08:49
  • 1
    @SyntaxT3rr0r `new Integer[2]` creates an array of length `2`, which has nothing to do with creating an object representing the value `2`, which would be `new Integer(2)`, which you should indeed replace with `Integer.valueOf(2)` or just `2`, to let the compiler do it. – Holger Sep 20 '19 at 08:52

6 Answers6

84

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

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
13

If they were simple int types, it would work.

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

sje397
  • 41,293
  • 8
  • 87
  • 103
8

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.

slfan
  • 8,950
  • 115
  • 65
  • 78
Nayan Srivastava
  • 3,655
  • 3
  • 27
  • 49
4

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
Bart van Heukelom
  • 43,244
  • 59
  • 186
  • 301
1

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.

MMKarami
  • 1,144
  • 11
  • 14
1

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

Andrzej Bobak
  • 2,106
  • 3
  • 28
  • 36