If you look in the API documentaton of class Integer, you'll see that there are different versions of the valueOf() method - there's one that takes a String, but there's also one that takes an int.
To explain the results you see:
n1 and n2 are different Integer objects, so if you compare them with ==, the result is false.
n3, n4 and n5 are Integer objects that are initialized via auto-boxing. n6 is an Integer object initialized with the return value of Integer.valueOf(). With auto-boxing, Integer.valueOf() is called behind the scenes.
Note that class Integer has a special caching mechanism. If you call Integer.valueOf() with a value between -128 and 127, the method will return an Integer object out of the cache that it manages behind the scenes. If you call Integer.valueOf() with the same input value multiple times (as you are doing with n3, n4, n5 and n6), it will return a reference to the same Integer object in the cache.
So if you compare those variables with ==, you'll get true - because the variables refer to the same Integer object.