9

I am comparing 2 pieces of code. First

Integer i=3;
Integer j=3;
if(i==j)
   System.out.println("i==j");  //prints i==j              

Second,

Integer i=3;
Integer j=new Integer(3);
if(i==j)
   System.out.println("i==j"); // does not print

I have doubt that in the first snippet why i==j is being printed? Shouldn't the references be different?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Shruti Rawat
  • 687
  • 6
  • 11
  • 24
  • Something to do with refernece, new, Objects, compairing memory addresses #Idk #CIS20...Somthing – DotNetRussell Jul 05 '13 at 17:35
  • `==` compare references not values, when you assign. In fist case both `i`, `j` points to same integers in memory. where in second case using new you create two new instance of object integer with same value 3. – Grijesh Chauhan Jul 05 '13 at 17:38
  • This is not a duplicate of the linked question. Notice that question was closed as a "not a real question" due to a mistaken premise that `new Integer(1) == new Integer(1)`, which isn't true. – John Kugelman Jul 05 '13 at 17:41
  • @JohnKugelman - It's the same question, just inverted, which the answer to that question covers. – Brian Roach Jul 05 '13 at 17:42
  • It's *not* the same question. Jon Skeet posted a similar answer but the question is quite different! – John Kugelman Jul 05 '13 at 17:43
  • @JohnKugelman: Agreed, although it amuses me that my answer in the linked question *does* answer this question... but not as well (IMO) as my answer in this one :) – Jon Skeet Jul 05 '13 at 17:43
  • 1
    @AMR: No, that is not the case at all. – jason Jul 05 '13 at 17:43

9 Answers9

18

It's to do with how boxing works. From the JLS section 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.

Basically, a Java implementation must cache the boxed representations for suitably small values, and may cache more. The == operator is just comparing references, so it's specifically detecting whether the two variables refer to the same object. In the second code snippet they definitely won't, as new Integer(3) definitely isn't the same reference as any previously created one... it always creates a new object.

Due to the rules above, this code must always give the same result:

Integer x = 127;
Integer y = 127;
System.out.println(x == y); // Guarantee to print true

Whereas this could go either way:

Integer x = 128;
Integer y = 128;
System.out.println(x == y); // Might print true, might print false
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • You should explain == comparison. – William Morrison Jul 05 '13 at 17:36
  • 2
    @William Morrison: Disagree. The OP clearly already gets that `==` is reference equality. The issue is that he mistakenly expects the references to be different (that is, the missing concept here is "interning" for some primitives, not not grokking `==`). – jason Jul 05 '13 at 17:37
  • 1
    I'm not messing with anyone. Perhaps I'm mistaken. I prefer excessively thorough explainations... – William Morrison Jul 05 '13 at 17:38
  • @WilliamMorrison: Is the edited answer better? I included `==` behaviour at the same time as explaining that `new Integer(3)` would definitely create a new object. (Despite the other comments, I have no problem with including some extra explanation here...) – Jon Skeet Jul 05 '13 at 17:40
  • 3
    @WilliamMorrison So, according to you, every explanation should start with: "In the beginning, there was the word ..." – Ingo Jul 05 '13 at 17:40
  • Yes I really like this answer now, great job. – William Morrison Jul 05 '13 at 17:41
  • Very interesting that the pooling is defined in the JLS specification, given that for Integer's case, it's done via the Integer class and not the JVM. – Steve Kuo Jul 05 '13 at 19:20
  • 1
    If Jon Skeet answer you question you only have to say thank you, because surely is correct, don't say "You should ..." lol – ncubica Jul 05 '13 at 19:34
6

Java pools integers between -128 and 127 and hence both the references are the same.

Integer i=3;
Integer j=3;

This results in autoboxing and 3 is converted to Integer 3. So for i is referring to an Integer object that is in constant pool, now when you do j=3, the same reference as that of i is assigned to j.

Whereas below code:

Integer j=new Integer(3);

always results in a new Integer creation, in heap. This is not pooled. And hence you see that both reference are referring to different objects. Which results in

Integer i=3;
Integer j=new Integer(3);
if(i==j)
   System.out.println("i==j"); // **does not print**
ajay.patel
  • 1,957
  • 12
  • 15
3

I have doubt that in the first snippet why i==j is being printed? Shouldn't the references be different?

Because,

    Integer i=3;
    Integer j=3;

are internally using Integer#valueOf() to perform autoBoxing . And oracle doc says about valueOf() method that:

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.

Since the value 3 is cached therefore, both variables i and j are referencing the same object. So, i==j is returning true. Integer#valueOf() uses flyweight pattern.

Vishal K
  • 12,976
  • 2
  • 27
  • 38
3
Integer i=3;
Integer j=3;
if(i==j)System.out.println("i==j");

Here, 3 is being auto-boxed and hence i and j point to the same Integer.

Integer i=3;
Integer j=new Integer(3);
if(i==j)System.out.println("i==j"); // does not print

Here, i points to the auto-boxed Integer whereas j points to a new Integer and hence there references fail the equals == operator test.

But, here's some more food for thought.

Integer i=300;
Integer j=300;
if(i!=j)System.out.println("i!=j"); // prints i!=j

Why? Because, auto-boxing shares Integer instances between -128 to 127 only. This behaviour, however, may differ between different Java implementations.

Ravi K Thapliyal
  • 51,095
  • 9
  • 76
  • 89
  • `Integer`'s pooling is not done by the JVM. It's entirely done by `Integer`. See `Integer`'s source code. – Steve Kuo Jul 05 '13 at 19:16
  • @SteveKuo I just checked `Integer.valueOf()` and yes the range is bounded by `Integer` between -128 to `IntegerCache.high` (127). I've corrected my answer. Thanks. – Ravi K Thapliyal Jul 05 '13 at 19:30
1

No they shouldn't, because java can use pre-fabricated Integer objects for small numbers when autoboxing.

Ingo
  • 36,037
  • 5
  • 53
  • 100
0

Because in the second peice of code your first integer is being auto-boxed while the second is not.

This means a new Integer instance is being created on the fly. These 2 object instances are different. The equality check will return false there as the two instances are actually different pieces of memory.

William Morrison
  • 10,953
  • 2
  • 31
  • 48
  • 1
    No, it's the *first* piece of code which is using autoboxing in both cases; the second uses it only for the first value. – Jon Skeet Jul 05 '13 at 17:34
  • I was referring to the first integer, not the second. – William Morrison Jul 05 '13 at 17:35
  • That was extremely unclear. It's *still* unclear from this answer why the first piece of code prints "i==j", because you haven't explained anything about the caching nature of boxing. – Jon Skeet Jul 05 '13 at 17:39
  • Yes it was unclear I suppose. And I agree about neglecting to explain auto-boxing adequately. Yours is much better. – William Morrison Jul 05 '13 at 17:40
0

Interpreter/JIT optimizer can put all 3's in same box. But if you force a "new" then you get another address.

Try

 j=8; // after initialization of i and j

then see the j's address changed for first version.

huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97
0

In a similar fashion to strings, when autoboxing is used, such as in

Integer i = 3;
Integer j = 3;

Java can draw from a pool of prefabricated objects. In the case of j, there's already an Integer instance representing the value of 3 in the pool, so it draws from that. Thus, i and j point to the same thing, thus i == j.

In your second example, you're explicitly instantiating a new Integer object for j, so i and j point to different objects, thus i != j.

Dancrumb
  • 26,597
  • 10
  • 74
  • 130
0

In Following Piece of Code:

Integer i=3;
Integer j=3;
if(i==j)
   System.out.println("i==j");

Here, "==" compares reference with each other rather than the value. So, Integer i and j both are referring to same reference in the memory.

while in Following Piece of Code:

Integer i=3;
Integer j=new Integer(3);
if(i==j)
   System.out.println("i==j");

The reference to both values are changed because 'j' is newly created object/reference of Integer in memory while 'i' is just referring to a value.

Therefore, the output of 1st code is "i==j" and 2nd code does not have any output.

Hope this helps.

emphywork
  • 448
  • 1
  • 4
  • 15