How != and == operators work on Integers in Java? [duplicate]

The following code seemed really confusing to me since it provided two different outputs.The code was tested on jdk 1.7.

public class NotEq {

public static void main(String[] args) {

    ver1();
    System.out.println();
    ver2();
}

public static void ver1() {
    Integer a = 128;
    Integer b = 128;

    if (a == b) {
        System.out.println("Equal Object");
    }

    if (a != b) {
        System.out.println("Different objects");
    }

    if (a.equals(b)) {
        System.out.println("Meaningfully equal.");
    }
}

public static void ver2() {
    Integer i1 = 127;
    Integer i2 = 127;
    if (i1 == i2) {
        System.out.println("Equal Object");
    }

    if (i1 != i2){
        System.out.println("Different objects");
    }
    if (i1.equals(i2)){
        System.out.println("Meaningfully equal");
    }
}

}

Output:

[ver1 output]
Different objects
Meaningfully equal.

[ver2 output]
Equal Object
Meaningfully equal

Why the == and != testing produces different results for ver1() and ver2() for same number much less than the Integer.MAX_VALUE? Can it be concluded that == checking for numbers greater than 127 (for wrapper classes like Integer as shown in the code) is totally waste of time?


Solution 1:

Integers are cached for values between -128 and 127 so Integer i = 127 will always return the same reference. Integer j = 128 will not necessarily do so. You will then need to use equals to test for equality of the underlying int.

This is part of the Java Language Specification:

If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

But 2 calls to Integer j = 128 might return the same reference (not guaranteed):

Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.

Solution 2:

Because small integers are interned in Java, and you tried the numbers on different sides of the "smallness" limit.

Solution 3:

There exist an Integer object cache from -128 and up to 127 by default. The upper border can be configured. The upper cache border can be controlled by VM option -XX:AutoBoxCacheMax=<size>

You are using this cache when you use the form:

 Integer i1 = 127;

or

Integer i1 = Integer.valueOf(127);

But when you use

Integer i1 = new Integer(127);

then you're guaranteed to get a new uncached object. In the latter case both versions print out the same results. Using the cached versions they may differ.