Confusion about ==

P Ventura
Ranch Hand
Posts: 42
It's a bit complicated, but I need your help.

I know that
a) i2!= i1 because are different references;
b) i1 == i3 for 100 and i1 !=i3 for a value > 127 (I don't remember which chapter of K&B states this)

Question:
Why i1 == i for every value (also > 127)? It's the same as b) !
What is the diffence with b?

Chris Hurst
Ranch Hand
Posts: 443
3
One is boxing in which case small integers map to the same object as you say.

The one that is confusing you is unboxing i.e. comparing literal integers so
that works for any integer size.

public class SCJP1 {
public static void main(String [] args) {
Integer j = 10;
boolean b = j==255;

}
}

The first line invokes Integer.valueOf to change 10 into an integer but the boolean comparison results in Inter.intValue being called on J prior to the integer comparison.

The trick is to realize in one scenario you are comparing objects in the other primitives.

I have to admit I haven't seen the strict language definition of this I've just looked at the physical byte code my eclipse is kicking out ;-). If anyone has the relevant language doc post it as mine seems to miss it out.

0 bipush 10
2 invokestatic #21 <java/lang/Integer.valueOf>
5 astore_1
6 aload_1
7 invokevirtual #25 <java/lang/Integer.intValue>
10 sipush 255
13 if_icmpne 20 (+7)
16 iconst_1
17 goto 21 (+4)
20 iconst_0
21 istore_2
22 return

Jesper de Jong
Java Cowboy
Saloon Keeper
Posts: 15354
39
The trick is in how autoboxing works and in the method Integer.valueOf(...).

When an int (primitive) is converted to an Integer (object) with autoboxing, this is done by calling the method Integer.valueOf(...) behind the scenes. So if you do this:

Integer i1 = 100;

then the compiler changes this at compile time to:

Integer i1 = Integer.valueOf(100);

Now, the method Integer.valueOf(...) has an optimization. When you call it with a value between -128 and 127, it does not create a new Integer object. The method maintains a cache of Integer objects with those values, and instead of a new Integer object it returns the existing object in the cache.

So if you call this method twice (explicitly or indirectly via autoboxing):

Integer i1 = 100;
Integer i3 = 100;

then you will get the same Integer object from the cache two times. If you compare i1 and i3 with ==, the result is true because i1 and i3 refer to the exact same Integer object.

Originally posted by P Ventura:
Question:
Why i1 == i for every value (also > 127)? It's the same as b) !
What is the diffence with b?

Because in that case, i1 is unboxed to an int, and the two int primitive values are compared. The Java Language Specification most likely describes that it works that way. If you want, you can try to find it in there.