In order to save memory, two instances of the following wrapper objects will always be == when their primitive values are the same: Boolean Byte Character from \u0000 to \u007f (7f is 127 in decimal) Short and Integer from -128 to 127
When == is used to compare a primitive to a wrapper object, the wrapper object will be unwrapped to its primitive value, and the comparison will be made between the two primitives' values.
This condition holds false when the objects are created using the new operator. In that case, the new operator will create a new object & hence the references pointing to them will differ.
So in your case, when you say :
What really happens is that only one Integer object is created in the pool & both the references point to that same object. But when you say :
Here, 2 new objects are created & i1 & i2 point to 2 different objects & hence the output is "DIFFERENT OBJECTS".
Behavior of equals() has universal so far as Wrappers are concerned because each wrapper implements the equals method of the Object class obviously. No matter in what way you create the wrapper object, equals will always return true if values are same.
Question only arises in case of ==.
You know the rules that says in the range of byte if two wrappers created without using "new" operator will result true. (I mean using autoboxing technique)
It is all about what Java language designers thought to save memory in case value is within -128 to 127.