3

Normally, references to objects in the Java library can't be compared using ==, but I just checked:

Integer x = 5;
Integer y = x + 1;
Integer z = y - 1;
x.equals(z)
true   (boolean)
x == z
true   (boolean)

Is that just an artifact of my IDE, or are Java Integer objects guaranteed to point to the same Integer when they have the same value? The latter guarantee would simplify some code I'm writing.

  • Yes for all 1 byte numbers because the JLS demands it. Try with larger numbers. Also if you explicitly generate integers you'll be out of luck too obviously, the guarantee only holds for auto boxing – Voo Nov 02 '15 at 15:49
  • 1
    As with all "value objects" you should never rely on object identity. – Meno Hochschild Nov 02 '15 at 15:51
  • @resueman And where in your example are you using autobixing? – Voo Nov 02 '15 at 15:56

3 Answers3

8

Are Java Integers always == when they're .equals()?

No. In the normal case, you cannot rely on == with Integer instances when attempting a numeric value comparison. For that you must either unbox them to int before comparing, or use equals.

What you're seeing in your example is the fact that the JDK caches and reuses a limited number of Integer instances (for Integers representing -128 to 127). From Integer.valueOf(int):

This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

Now, your code is using boxing conversions rather than Integer.valueOf, and the specification doesn't say that boxing conversions use Integer.valueOf, and yet it's likely that that's exactly what they do (in effect; e.g., that both the boxing conversion and Integer.valueOf use the same underlying mechanism and cache).

You can see that == is not reliable for Integer instances if you use a different value: (live copy)

Integer x = 524;    // <==== Changed
Integer y = x + 1;
Integer z = y - 1;
System.out.println("equals? " + x.equals(z));
System.out.println("==? " + (x == z));

Output (probably, and it's what I get on IDEOne, but again the docs say Integer may cache other values):

equals? true
==? false
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

Not always but for specific range.

That catch here is that Java catches the Integer values in the ranges -128 to 127. Hence they return true when you do ==

Here is the language specification for the same

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

And I remember the reason for this is to achieve the performance on small devices.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
2

No, it is not guaranteed. For certain values (especially smaller, more commonly used ones) the value will get internalized and the same object reference will be reused. If you try the same test with 3,279,831 it will probably return false.

Matt
  • 3,303
  • 5
  • 31
  • 53