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

54,536

Solution 1

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

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

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

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

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);
}       
Share:
54,536

Related videos on Youtube

vipin k.
Author by

vipin k.

Updated on February 04, 2022

Comments

  • vipin k.
    vipin k. over 2 years
    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.

  • Andreas Petersson
    Andreas Petersson over 14 years
    note that values smaller than 127 will be ignored by java and values bigger than Integer.MAX_VALUE-128 will be capped.
  • MetroidFan2002
    MetroidFan2002 over 14 years
    Integers are cached for byte values in Java 5 and higher, making new Integer(1) == new Integer(1). However, this is not the case in Java 1.4 or lower, so beware if you have to eventually downgrade to that environment.
  • Andreas Petersson
    Andreas Petersson over 14 years
    no, this is wrong. new Integer(1) == new Integer(1) is false regardless of the jvm. AFAIK no compiler will cheat at the "new" keyword. it MUST always instantiate a new object.
  • Kyle
    Kyle over 7 years
    Is this still the case in Java 8 as of October 2016?
  • Holger
    Holger over 5 years
    @AndreasPetersson a compiler may cheat, but by replacing the entire new Integer(1) == new Integer(1) expression with the constant false, so it wouldn’t bear object allocations, but the standard conforming result still has to be false.
  • Andreas Petersson
    Andreas Petersson over 5 years
    @Holger interesting point. But It is technically possible to replace the Integer class from the JDK with a custom impl... (don't ask why somebody would be that insane) - then it could have side effects that are not allowed to optimize away
  • Holger
    Holger over 5 years
    @AndreasPetersson sure. “compiler” means the JIT compiler, which does precisely know the actual implementation class and may only optimize, if the constructor has no side effects. Or optimize the expression to only reproduce the side effects, followed by using false. Actually, this may already happen today, as a side effect of applying Escape Analysis and Scalar Replacement.
  • Stephen C
    Stephen C almost 5 years
    Note: the JLS changed in Java 9. This is now only guaranteed for compile time constant expressions; see update to accepted answer.
  • Michael Lloyd Lee mlk
    Michael Lloyd Lee mlk almost 5 years
    Not sure how the second example can ever be false as it is a basic object assignment, nothing to do with boxing at all. Do you mean something more like: ``` Integer boxy(int i) { return i; } Integer b1 = boxy(127); Integer b2 = boxy(127); b1 == b2; // may be false ```
  • Andreas Petersson
    Andreas Petersson almost 5 years
    @MichaelLloydLeemlk you are right, i reverted the edit. there were some subtle changes to §5.1.7 widening its applicability to other types than int/Integer.
  • user3739116
    user3739116 over 4 years