21

The output of current program is "Strange". But both the variables share the same reference. Why are the second and third comparisons not true?

Integer a;
Integer b;
a = new Integer(2);
b = a;
if(b == a) {
    System.out.println("Strange");
}
a++;
if(b == a) {
    System.out.println("Stranger");
}
a--;
if(b == a) {
    System.out.println("Strangest");
}

Output: Strange

Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135

3 Answers3

24

That's the artifact of autoboxing and a fact that Integer is immutable in Java.

The a++ and a-- are translated to roughly this.

int intA = a.getInt( );
intA++;
a = Integer.valueOf( intA ); // this is a reference different from b
Alexander Pogrebnyak
  • 44,836
  • 10
  • 105
  • 121
  • 17
    Note that if you replace `a = new Integer(2)` with `a = Integer.valueOf(2)`, "Strangest" will also be printed since it will use the integer cache for getting the instance. – Mark Peters Jun 21 '10 at 14:18
  • What do you mean by integer cache in your comment. can you elaborate ? – restrictedinfinity Jun 21 '10 at 14:35
  • 5
    @restrictedinfinity. At least in Sun's Java, Byte, Short and Integer have a cache of 256 values ranging from -128 to 127 inclusive that are served by `Type.valueOf( )` method. So in our case after `a--` the int value is `2` and that would be the same that we have started with, so `Integer.valueOf( 2 )` would have returned the same `Integer` object. Note, that `Long` type does not have a cache, therefore `Long.valueOf` always returns a new object. – Alexander Pogrebnyak Jun 21 '10 at 14:41
  • @Alexander: It can be safely assumed that this behaviour holds true for all JVM implementations since it is a part of the specification. – Sanjay T. Sharma Jan 24 '11 at 14:05
  • @Sanjay it is part of the specification, but it only guarantees to cache -128 to +127. However, implementations may cache more than this if they choose. This means if it chooses to cache more, an `==` comparison of, say `valueOf(200)` may prove to be `true` on some implementations but `false` on others. – corsiKa Apr 06 '11 at 00:49
  • 1
    @glowcoder: I was actually correcting the statement "At least in Sun's Java, Byte, Short and Integer have a cache of 256 values ranging from -128 to 127 inclusive that are served by Type.valueOf( ) method" since he didn't really need to mention "Sun" Java; this behaviour is consistent across all implementations since it's a part of the specification. Of course, as you correctly observed, nothing definitive can be said about values which don't fall in the range decided by the specification. – Sanjay T. Sharma Apr 06 '11 at 05:45
8
  • Strage - it's obvious, the two variables point to the same object

  • not Stranger because of autoboxing. Integer is immutable, so each operation on it creates a new instance.

  • not Strangest, because of the previous point, and because you have used new Integer(..) which ignores the cache that is used for the byte range. If you use Integer.valueOf(2) initially, then the cached Integers will be used and Strangest will also be printed.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
0

An Integer object is immutable, any change in an existing object will create a new object. So after a++, a new object will be created and a will start pointing to that new object while b is still pointing to the old object. Hence, after a++, a and b are pointing to different objects and a == b will always return false.

with respect to the mentioned example :

Integer a; //created Integer reference   
Integer b;  //created Integer reference  
a = new Integer(2);//created new Integer Object and a reference is assigned to that new object   
b = a;//b also start pointing to same Integer object   
if(b == a) { // b==a will be true as both are pointing to same object   
System.out.println("Strange");   
}
a++; //after a++ , a new Integer object will be created (due to Integer immutablity and a will point to that new object while b is still pointing to old), so b==a will be false   
if(b == a) { 
System.out.println("Stranger"); 
}   
a--; //again a new Integer Object will be created and now a will start pointing to that new Object , so b==a will be false   
if(b == a) { 
System.out.println("Strangest");
}
irfan
  • 878
  • 9
  • 10