67

I'm reading SCJP Java 6 by Kathy Sierra and Bert Bates and this book is confusing me so much. On page 245 they state that the following code below.

Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2)
System.out.println("different objects");

//Prints output
different objects

Then on the very next page they have the following code

Integer i3 = 10;
Integer i4 = 10;
if(i3 == i4)
System.out.println("same objects");

//Prints output
same objects

I'm so confused! When I try this out on my own it seems that you cannot use the == to compare the same way you would use equals() method. Using the == always gives me 'false' even if the Integer variables are set to the same value (i.e. 10). Am I correct? Using the == to compare the same Integer object (with same values) will always result in 'false'

Peter Perháč
  • 20,434
  • 21
  • 120
  • 152
dido
  • 3,347
  • 11
  • 34
  • 42
  • 2
    I think this link can help you: http://stackoverflow.com/questions/1514910/when-comparing-two-integers-in-java-does-auto-unboxing-occur – Tarik Apr 14 '12 at 00:31
  • 1
    duplicate of http://stackoverflow.com/questions/5277881/why-arent-integers-cached-in-java – Patrick Apr 14 '12 at 01:18
  • 1
    And this: http://stackoverflow.com/questions/5117132/integer-wrapper-objects-share-the-same-instances-only-within-the-value-127, http://stackoverflow.com/questions/8427416/why-is-true-for-some-integer-objects – Patrick Apr 14 '12 at 01:20
  • 1
    Possible duplicate of [Why does 128==128 return false but 127==127 return true in this code?](http://stackoverflow.com/questions/1700081/why-does-128-128-return-false-but-127-127-return-true-in-this-code) – Tom Oct 07 '15 at 07:46

8 Answers8

76

The key to the answer is called object interning. Java interns small numbers (less than 128), so all instances of Integer(n) with n in the interned range are the same. Numbers greater than or equal to 128 are not interned, hence Integer(1000) objects are not equal to each other.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    Wow! I just saw that too. Why?? That's so confusing. What is the reasoning behind this? – dido Apr 14 '12 at 00:38
  • 12
    note that only the object obtained from literals, autoboxing and `Integer.valueOf()` are interned objects while those constructed with `new Integer` are always distinct objects – ratchet freak Apr 14 '12 at 00:38
  • I seem to remember that also goes for small Strings, but am not sure whether this is true and if so, what is considered a small String. Do you know anything about that? – G. Bach Apr 14 '12 at 00:38
  • @G.Bach No, that has nothing to do with size. String constants are interned and you can call `intern` on your string variables for the same effect, that's all. And the why is simple: We need to store string constants somewhere anyhow and for small integers it's just a performance/memory optimization – Voo Apr 14 '12 at 00:45
  • 2
    @dido One of the reasons behind interning integers is an attempt to save memory and to a certain extent - to save time as well. When `Integer` objects are used as keys in hash maps or as objects in hash sets, the percentage of small integers is disproportionally large. By interning them you can skip re-allocation of memory to hold identical copies of immutable objects that are equal to each other, and let the equality compare finish faster by checking reference equality first. Best of all, it hardly costs you anything in terms of CPU cycles, so it was an easy decision to make. – Sergey Kalinichenko Apr 14 '12 at 00:49
  • Java is not interning small numbers. `Integer` itself is doing the object pooling. – Steve Kuo Apr 14 '12 at 01:05
  • @SteveKuo You are right - I used the term loosely to mean both the language and its libraries, specifically java.lang.Integer. The two are more or less inseparable (e.g. Java compiler "knows" how to box `int` constants as `Integers`) so I think this usage is justified. – Sergey Kalinichenko Apr 14 '12 at 01:08
  • I've seen cases where this interning caused serious peformance degradation. I was creating a lot of Integers in a tight loop, and the instantiation cost was not trivial. – James Scriven Apr 14 '12 at 01:10
  • @JamesScriven As any optimization technique, interning manually can go wrong. There is a cost difference between doing it manually to lots of integers in a tight loop, and doing it ahead of time to a small number of integers. – Sergey Kalinichenko Apr 14 '12 at 01:21
  • @JamesScriven java does not intern Integer dynamically, the interned Integer values are allocated at startup. It only does a range check (value < internedValues.length)when autoboxing int. – josefx Apr 16 '12 at 19:03
  • @josefx If I recall it correctly, it also checks for it in the `Integer.valueOf` method. – Sergey Kalinichenko Apr 16 '12 at 19:05
  • @dasblinkenlight that is the range check I was referring to, after all autoboxing is performed using valueOf. with only I wanted to refer to the overhead being only a range check (not a native English speaker). – josefx Apr 16 '12 at 19:32
20

If you look at the source code for Integer you'll see that Integer.valueOf(int) pools all values -128 to 127. The reason is that small Integer values are used frequently and are thus worthy of being pooled/cached.

Taken straight from Integer.java:

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

Note that this pooling is implementation specific and there's no guarantee of the pooled range.

The answers about interning are correct in concept, but incorrect with terminology. Interning in Java normally implies that the Java runtime is performing the pooling (such as String's intern). In Integer's case it's the class itself that is doing the pooling. There's no JVM magic involved.

Steve Kuo
  • 61,876
  • 75
  • 195
  • 257
  • 1
    Actually, the caching of `Integer` objects for `int` values in the range [-128, 127] is specified in [the API docs](http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#valueOf%28int%29), so that part of the range is, in fact, guaranteed. – Ted Hopp Apr 23 '13 at 01:35
7

The above answer about Interning is right on. Something to consider though if you do:

Integer i3 = new Integer(10);
Integer i4 = new Integer(10);

You will not have the new objects since you have created new objects explictly. If you write the code as follows it will be interned:

Integer i3 = Integer.valueOf(10);
Integer i4 = Integer.valueOf(10);

They will now be the same object again. If you take a look at the valueOf Method inside of the Integer.java class in the src.zip file you can see where it checks to see if the value of the int is outside of -128 to 127 it calls the new Integer class otherwise it loads it from the cache.

haskovec
  • 370
  • 3
  • 12
3
Integer i1 = 1000;
Integer i2 = 1000;

The compiler 'boxes' the int 1000 as Integer object. To do this it converts the source to the following:

Integer i1 = Integer.valueOf(1000);
Integer i2 = Integer.valueOf(1000);

Now valueOf could be a simple call to new Integer(1000) however creating a new Integer object every time an int is boxed would cost both time and space. To avoid this the Integer class keeps an array of Integer objects for a limited range of int values.

if(value> maxRange || value< minRange){
     //not in pool return new Integer
     return new Integer(value);
}else{
     //return pooled Integer object
     //for the value, pool contains all Integer
     //values from minRange to maxRange
     return integerPool[value-minRange];
}

The speed gained vs. the memory lost to this can be adjusted by setting the range with a jvm argument at program start (afaik it defaults to -127 to 128).

josefx
  • 15,506
  • 6
  • 38
  • 63
0

When the Java == operator is used to compare anything other than primitive types, it checks for referential equality; this applies even when the things being compared are wrapped primitives. Further, the valueOf method and compiler-generated autoboxing statement are generally free to arbitrarily return a new object which will not be reference-equal to any other previously-existing reference, or to return a reference to an existing object (which would, of course, be reference-equal to any pre-existing reference identifying the same object). Implementations are required to maintain a "pool" of Integer instances for values -128 to 127, such that all calls to Integer.valueOf on any particular number within that range will return references to the same object, but other than that an implementation would be free to do something like

static Integer [] intPool = new Integer[256];

public Integer valueOf(int n)
{
  int hash = (n*0x18675309) >>> 24;
  Integer instance = intPool[n];
  if (instance == null && instance.value != n)
  {
    instance = new Integer(n);
    intPool[hash] = instance ;
  }
  return instance;
}

I don't particularly expect Java implementations to do something like that, since in many cases the "cache hit" ratio could be near 0% and the extra time spent looking for instances in the cache would be wasted. Nonetheless, there is never any guarantee that a reference returned by instanceOf won't match some previous reference returned by that method (even if it doesn't match the last reference returned by that method, some caching algorithms might possibly cause it to return an earlier reference, especially if the pool is shared by multiple threads without locking. The lack of locking will never cause the code to return anything other than a reference to an integer with the correct value, but could cause unpredictable variations in which returned references compare equal). Only reference to Integer objects created directly using the constructor new Integer(n) are guaranteed to be unique; code which expects any reference returned by valueOf to not match any reference returned by valueOf, without having actually observed that it does not match, should be considered broken.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

String comparison and integer comparison using == and != gives boolean results not as we expect.So be careful and make sure the possible unknown outcomes do not hinder the performance , reliability and accuracy of your software.

0

"==" always compare the memory location or object references of the values. equals method always compare the values.but equals also indirectly uses the "==" operator to compare the values. Integer uses Integer cache to store the values from -128 to +127.If == operator is used to check for any values between -128 to 127 then it returns true. if any value between -128 to 127 as

Integer i1 = -128; 
Integer i2 = -128; 
System.out.println(i1 == i2); // returns true

other than the above range then it returns false

Integer i1 = 1000;
Integer i2 = 1000;
System.out.println(i1 == i2); // returns false

Refer the link for some additional info

vijay
  • 926
  • 7
  • 15
0

According to jls-5.1.7

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.

So, any number between -128 and 127 is cached by Interger class.
Remember, when comparing two objects always use equals method.

The caching code is written in IntegerCache class which is member of Integer class.

Here is the code snippet:

 /**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

References

Aniket Kulkarni
  • 12,825
  • 9
  • 67
  • 90