######## Key points extracted from below ####################
1. Consider the following snippet of code:
Integer aa = new Integer(100);
Integer bb = new Integer(100);
Integer cc = new Integer(505);
System.out.println(aa == bb); // will print false
System.out.println(aa == cc); // will print false
In this snippet of code, no autoboxing/unboxing takes place. Here, aa == bb and aa == cc compare the references of aa, bb and cc, not their values. Every object created with the new operator has a unique reference.
2. For Integer.valueof() method, for all values between –128 and 127, the Integer class caches Integer object references
#####################################
Comparison Operators and AutoBoxing/Unboxing
I will discuss comparison operations ==, >, >=, <, <=. Only == (logical equality operator) can be used with both reference type and primitive types. The other operators must be used only with primitive types.
Let’s discuss the easy ones (>, >=, < and <=) first. If a numeric wrapper object is used with these comparison operators, it must be unboxed and the corresponding primitive type used in the comparison. Consider the following snippet of code:
Integer a = 100;
Integer b = 100;
System.out.println("a : " + a);
System.out.println("b : " + b);
System.out.println("a > b: " + (a > b));
System.out.println("a >= b: " + (a >= b));
System.out.println("a < b: " + (a < b));
System.out.println("a <= b: " + (a <= b));
a : 100
b : 100
a > b: false
a >= b: true
a < b: false
a <= b: true
There is no surprise in the above output. If you mix the two types, reference and primitive, with these comparison operators, you still get the same results. First, the reference type is unboxed and a comparison with the two primitive types takes place. For example,
if (101 > new Integer(100)) {
// Do something
}
is converted to
if(101 <= (new Integer(100)).intValue()) {
// Do something
}
Now, let’s discuss the == operator and the autoboxing rules. If both operands are primitive types, they are compared as primitive types using a value comparison. If both operands are reference types, their references are compared. In these two cases, no autoboxing/unboxing takes place. When one operand is a reference type and another is a primitive type, the reference type is unboxed to a primitive type and a value comparison takes place. Let’s see examples of each type.
Consider the following snippet of code. It is an example of using both primitive type operands for the == operator.
int a = 100;
int b = 100;
int c = 505;
System.out.println(a == b); // will print true
System.out.println(a == c); // will print false
Consider the following snippet of code:
Integer aa = new Integer(100);
Integer bb = new Integer(100);
Integer cc = new Integer(505);
System.out.println(aa == bb); // will print false
System.out.println(aa == cc); // will print false
In this snippet of code, no autoboxing/unboxing takes place. Here, aa == bb and aa == cc compare the references of aa, bb and cc, not their values. Every object created with the new operator has a unique reference.
Now, here’s a surprise: consider the following snippet of code. This time you are relying on autoboxing.
Integer aaa = 100; // Boxing – Integer.valueOf(100)
Integer bbb = 100; // Boxing – Integer.valueOf(100)
Integer ccc = 505; // Boxing – Integer.valueOf(505)
Integer ddd = 505; // Boxing – Integer.valueOf(505)
System.out.println(aaa == bbb); // will print true
System.out.println(aaa == ccc); // will print false
System.out.println(ccc == ddd); // will print false
You used aaa, bbb, ccc, and ddd as reference types. How is aaa == bbb true whereas ccc == ddd false? All right. This time, there is no surprise coming from the autoboxing feature. Rather, it is coming from the Integer.valueOf() method. For all values between –128 and 127, the Integer class caches Integer object references. The cache is used when you call its valueOf() method. For example, if you call Integer.valueOf(100) twice, you get the reference of the same Integer object from the cache that represents the int value of 100. However, if you call Integer.valueOf(n), where n is outside the range –128 to 127, a new object is created for every call. This is the reason that aaa and bbb have the same reference from the cache, whereas ccc and ddd have different references. Byte, Short, Character and Long classes also cache object references for values in the range –128 to 127.