Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?

JavaIntegerComparisonPass by-ReferencePass by-Value

Java Problem Overview


class D {
    public static void main(String args[]) {
        Integer b2=128;
        Integer b3=128;
        System.out.println(b2==b3);
    }
}

Output:

false

class D {
    public static void main(String args[]) {
        Integer b2=127;
        Integer b3=127;
        System.out.println(b2==b3);
    }
}

Output:

true

Note: Numbers between -128 and 127 are true.

Java Solutions


Solution 1 - Java

When you compile a number literal in Java and assign it to a Integer (capital I) the compiler emits:

Integer b2 =Integer.valueOf(127)

This line of code is also generated when you use autoboxing.

valueOf is implemented such that certain numbers are "pooled", and it returns the same instance for values smaller than 128.

From the java 1.6 source code, line 621:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

The value of high can be configured to another value, with the system property.

> -Djava.lang.Integer.IntegerCache.high=999

If you run your program with that system property, it will output true!

The obvious conclusion: never rely on two references being identical, always compare them with .equals() method.

So b2.equals(b3) will print true for all logically equal values of b2,b3.

Note that Integer cache is not there for performance reasons, but rather to conform to the JLS, section 5.1.7; object identity must be given for values -128 to 127 inclusive.

Integer#valueOf(int) also documents this behavior:

> this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

Solution 2 - Java

Autoboxing caches -128 to 127. This is specified in the JLS (5.1.7).

> 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.

A simple rule to remember when dealing with objects is - use .equals if you want to check if the two objects are "equal", use == when you want to see if they point to the same instance.

Solution 3 - Java

Using primitive data types, ints, would produce true in both cases, the expected output.

However, since you're using Integer objects the == operator has a different meaning.

In the context of objects, == checks to see if the variables refer to the same object reference.

To compare the value of the objects you should use the equals() method E.g.

 b2.equals(b1)

which will indicate whether b2 is less than b1, greater than, or equal to (check the API for details)

Solution 4 - Java

It is memory optimization in Java related.

> To save on memory, Java 'reuses' all the wrapper objects whose values > fall in the following ranges: > > All Boolean values (true and false) > > All Byte values > > All Character values from \u0000 to \u007f (i.e. 0 to 127 in decimal) > > All Short and Integer values from -128 to 127.

Solution 5 - Java

Have a look at the Integer.java, if the value is between -128 and 127, it will use the cached pool, so (Integer) 1 == (Integer) 1 while (Integer) 222 != (Integer) 222

 /**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}       

Solution 6 - Java

Other answers describe why the observed effects can be observed, but that's really beside the point for programmers (interesting, certainly, but something you should forget all about when writing actual code).

To compare Integer objects for equality, use the equals method.

Do not attempt to compare Integer objects for equality by using the identity operator, ==.

It may happen that some equal values are identical objects, but this is not something that should generally be relied on.

Solution 7 - Java

if the value is between -128 and 127, it will use the cached pool and this is true only when auto-boxing. So you will have below:

    public static void main(String[] args) {
        Integer a  = new Integer(100);
        Integer b = new Integer(100);
        System.out.println(a == b);         // false. == compare two instances, they are difference
        System.out.println(a.equals(b));    // true. equals compares the value

        Integer a2 = 100;
        Integer b2 = 100;
        System.out.println(a2 == b2);       // true. auto-boxing uses cached pool between -128/127
        System.out.println(a2.equals(b2));  // true. equals compares the value

        Integer a3 = 129;
        Integer b3 = 129;
        System.out.println(a3 == b3);       // false. not using cached pool
        System.out.println(a3.equals(b3));  // true. equals compares the value
    }
}

Solution 8 - Java

I wrote the following as this problem isn't just specific to Integer. My conclusion is that more often than not if you use the API incorrectly, you sill see incorrect behavior. Use it correctly and you should see the correct behavior:

public static void main (String[] args) {
    Byte b1=127;
    Byte b2=127;

    Short s1=127; //incorrect should use Byte
    Short s2=127; //incorrect should use Byte
    Short s3=128;
    Short s4=128;

    Integer i1=127; //incorrect should use Byte
    Integer i2=127; //incorrect should use Byte
    Integer i3=128;
    Integer i4=128;

    Integer i5=32767; //incorrect should use Short
    Integer i6=32767; //incorrect should use Short

    Long l1=127L;           //incorrect should use Byte
    Long l2=127L;           //incorrect should use Byte
    Long l3=13267L;         //incorrect should use Short
    Long l4=32767L;         //incorrect should use Short
    Long l5=2147483647L;    //incorrect should use Integer 
    Long l6=2147483647L;    //incorrect should use Integer
    Long l7=2147483648L;
    Long l8=2147483648L;

    System.out.print(b1==b2); //true  (incorrect) Used API correctly
    System.out.print(s1==s2); //true  (incorrect) Used API incorrectly
    System.out.print(i1==i2); //true  (incorrect) Used API incorrectly
    System.out.print(l1==l2); //true  (incorrect) Used API incorrectly

    System.out.print(s3==s4); //false (correct) Used API correctly
    System.out.print(i3==i4); //false (correct) Used API correctly
    System.out.print(i5==i6); //false (correct) Used API correctly
    System.out.print(l3==l4); //false (correct) Used API correctly
    System.out.print(l7==l8); //false (correct) Used API correctly
    System.out.print(l5==l6); //false (correct) Used API incorrectly
    
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionvipin k.View Question on Stackoverflow
Solution 1 - JavaAndreas PeterssonView Answer on Stackoverflow
Solution 2 - JavaMichael Lloyd Lee mlkView Answer on Stackoverflow
Solution 3 - JavachrisbunneyView Answer on Stackoverflow
Solution 4 - JavaDeveloper Marius ŽilėnasView Answer on Stackoverflow
Solution 5 - JavayanghaognView Answer on Stackoverflow
Solution 6 - Javauser13463803View Answer on Stackoverflow
Solution 7 - JavaJacqueline P.View Answer on Stackoverflow
Solution 8 - JavathejartenderView Answer on Stackoverflow