"==" determines whether the reference variables refer to the same object
i.e. if Type obj = new Type();
obj1 = obj;
then both the reference variables refer to the same object Type(); isn't it?
now in our situation,
Integer i1 = 1000;
Integer i2 = 1000;
we have two different objects having two different reference variables, hence if (i1 != i2) then println statement gets executed
and remember that equals method checks for the content of the object
the content is same i.e. 1000 and 1000
hence i1.equals(i2) is true hence the meaningfully equivalent gets executed
But there is something weird with java, the equality depends upon the range of values we are providing
Read and remember following carefully :
Two instances of the wrapper objects Boolean, Byte, Character from \u0000 to \u007f and short and integer from -128 to 127 will always be == when their primitive values are same
Here i1 and i2 are created through Boxing and Integers created through boxing in the range -128 to 127 always pass the == test if their values are equal. Here i1 and i2 are greater than this range hence they pass != test. You make i1 and i2 smaller than this range and then
(i1!=i2) will return false
will be placed on literal pool and will share the same copy. Hence == will be evaluated to true.
And this works for direct assignments only. Objects created using new Integer() are always placed at Heap.
If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.