Thats the magic of Integer pool.
Firstly == is used to check the references(address) of 2 objects whereas equals() method is used to check the content of 2 objects.
So when you are writing Here you are creating the object i1 and storing the value 10, that's fine. Now So you must be thinking that Java will create another object i2 with again the same value 10 then you are thinking wrong because Java maintains the Integer pool where it stores the value if they are in the range -128 to 127.
Now lets see what happens when you first created the object i1 with value 10 then Java puts this value in Integer pool(since 10 was within the above range) and when again you are creating another object with the same value 10 Java will not create object and just pass a reference to the already created object i1. SO the summary is i1 and i2 are same object therefore .
Then you wrote So i3 object is created with value 1000 and then you wrote this time even though
i4 has the same value as i3, it will be created (i.e. i4 object will be created) because as mentioned above the range is -128 to 127. Therefore .
== compares just memory locations, in case of objects.
equals() just checks if two objects are meaningfully equal.
Just to save some memory, Java assigns all wrapper classes with same small values (-128 to 127), with the same address. And for larger values, different addresses.
As a result, using == for same small values, points to same location in the memory, and thus returning true. Using == with larger values, might not do so.
** It's not in the nature of Nature to live without creating beautiful things. **