As you all very well know sometimes Java uses object pools for wrappers and String types, sometimes it doesn’t.
For example:
Integer i1 = 1;
Integer i2 = 1;
Integer i3 = new Integer(1);
String s1 = "String";
String s2 = "String";
String s3 = new String ("String");
System.out.println("(i1 == i2) " + (i1 == i2));
System.out.println("(i2 == i3) " + (i2 == i3));
System.out.println("(s1 == s2) " + (s1 == s2));
System.out.println("(s2 == s3) " + (s2 == s3));
Execution result:
(i1 == i2) true
(i2 == i3) false
(s1 == s2) true
(s2 == s3) false
As you see boxing of primitives takes objects from the pool, creating of a Strings via string literal takes objects from the pool, too. Such objects are actually the same object (operator == returns true on them).
Other mechanisms of creating wrappers and Strings don’t take objects from the pool. Objects created these ways are actually different objects (operator == returns false on them).
What confuses me is the fact that the pool is used partially.
If its a memory issue, why not use the pool all of the times?
If its not a memory issue – why use it at all?
The question is – what are the reasons for implementing such behavior (= partial usage of the pool)?
The question is rather theoretical, but it has practical application – it can help understand how correctly use custom objects pools and of course understanding how Java works is always good.
Its a speed concern, allocating a new
Integerevery single time would be both time and memory expensive. But by the same token allocating at start up too much at start up uses tons of memory and time.Sadly it leads to some counter-intuitive behavior as you’ve found.
The result is this weird compromise that we have. The reasons for this behavior are discussed in the Java standard. (5.7)
tl;dr
It’s impossible to make it work perfectly, and it’s too weird to not have it work at all. So we have it work for “most” of the time.