Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't Integers cached in Java?

I know there are similar posts on the topic, but they don't quite address my question. When you do:

Integer a = 10; Integer b = 10; System.out.println("a == b: " + (a == b)); 

This will (apparently) print true most of the time because integers in the range [-128, 127] are somehow cached. But:

Integer a = new Integer(10); Integer b = new Integer(10); System.out.println("a == b: " + (a == b)); 

Will return false. I understand that I am asking for new instances of an Integer, but since boxed primitives are immutable in Java, and the machinery is already there to do the "right thing" (as seen in the first case), why does this happen?

Wouldn't it make more sense if all instances of an Integer with a 10 be the same object in memory? In other words, why don't we have "Integer interning" which would be similar to "String interning"?

Better yet, wouldn't it make more sense if instances of a boxed primitive representing the same thing, regardless of value (and type), be the same object ? Or at least respond correctly to ==?

like image 632
NullUserException Avatar asked Mar 11 '11 20:03

NullUserException


People also ask

What is integer cache in Java?

Java Integer Cache Implementation:Integer objects are cached internally and reused via the same referenced objects. This is applicable for Integer values in the range between –128 to +127. This Integer caching works only on auto-boxing. Integer objects will not be cached when they are built using the constructor.

How is integer stored in memory Java?

All Java integer types are stored in signed two's complement format. The sign takes up one bit. The remaining bits store the value itself and dictate the range of values that can be stored for each type. For example, a short value uses one bit for the sign and 15 bits to store the value.

Where are integers stored in Java?

Objects created with new keyword are stored on heap. Variables (references to those objects) and primitive types like int are stored on program's stack. Integer is not a special class in Java.

What is the range of integer class in Java?

Java max Int. As we know that the Java integer type 'int' has a range from –2,147,483,648 to 2,147,483,647 which is also from -231 to 231-1.


1 Answers

It should be very clear that caching has an unacceptable performance hit -- an extra if statement and memory lookup every time you create an Integer. That alone overshadows any other reason and the rest of the agonizing on this thread.

As far as responding "correctly" to ==, the OP is mistaken in his assumption of correctness. Integers DO respond correctly to == by the general Java community's expectation of correctness and of course by the specification's definition of correctness. That is, if two references point to the same object, they are ==. If two references point to different objects, they are not == even if they have the same contents. Thus, it should be no surprise that new Integer(5) == new Integer(5) evaluates to false.

The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.

If it were not for that, then Java implementations could totally cache new Object()s with a singleton.

And that should explain why new Integer(5) done 7 times must be required to create 7 unique Integer objects each containing the value 5 (because Integer extends Object).


Secondary, Less Important Stuff: One problem in this otherwise nice scheme results from the autoboxing and autounboxing feature. Without the feature you could not do comparisons such as new Integer(5) == 5. To enable these, Java unboxes the object (and does not box the primitive). Therefore new Integer(5) == 5 is converted to: new Integer(5).intValue() == 5 (and not new Integer(5) == new Integer(5).

One last thing to understand is that autoboxing of n is not done by new Integer(n). It is done internally by a call to Integer.valueOf(n).

If you think you understand and want to test yourself, predict the output of the following program:

public class Foo {   public static void main (String[] args) {     System.out.println(Integer.valueOf(5000) == Integer.valueOf(5000));     System.out.println(Integer.valueOf(5000) == new Integer(5000));     System.out.println(Integer.valueOf(5000) == 5000);     System.out.println(new Integer(5000) == Integer.valueOf(5000));     System.out.println(new Integer(5000) == new Integer(5000));     System.out.println(new Integer(5000) == 5000);     System.out.println(5000 == Integer.valueOf(5000));     System.out.println(5000 == new Integer(5000));     System.out.println(5000 == 5000);     System.out.println("=====");     System.out.println(Integer.valueOf(5) == Integer.valueOf(5));     System.out.println(Integer.valueOf(5) == new Integer(5));     System.out.println(Integer.valueOf(5) == 5);     System.out.println(new Integer(5) == Integer.valueOf(5));     System.out.println(new Integer(5) == new Integer(5));     System.out.println(new Integer(5) == 5);     System.out.println(5 == Integer.valueOf(5));     System.out.println(5 == new Integer(5));     System.out.println(5 == 5);     System.out.println("=====");     test(5000, 5000);     test(5, 5);   }   public static void test (Integer a, Integer b) {     System.out.println(a == b);   } } 

For extra credit, also predict the output if all the == are changed to .equals(...)

Update: Thanks to comment from user @sactiw : "default range of cache is -128 to 127 and java 1.6 onward you can reset the upper value >=127 by passing -XX:AutoBoxCacheMax= from command line"

like image 93
necromancer Avatar answered Oct 16 '22 20:10

necromancer