Card 05/ 08

ExampleDifficulty: Intermediate2 min

Flyweight in the Wild: Java's Integer.valueOf Cache

Integer.valueOf(100) returns the same object twice; Integer.valueOf(1000) does not.

Java's Integer.valueOf is a flyweight factory built into the JDK. Small integers are used constantly as boxed Integer objects, so the class keeps a cache of them and returns the stored object instead of creating a new one. This card asks you to predict which calls share an object, then shows the range the cache covers.

== on two objects in Java is true only when both references point to the same object. Four comparisons follow, each between two calls to Integer.valueOf with the same number.

java
Integer.valueOf(100) == Integer.valueOf(100)
Integer.valueOf(1000) == Integer.valueOf(1000)
Integer.valueOf(127) == Integer.valueOf(127)
Integer.valueOf(128) == Integer.valueOf(128)
Which of the four are true? Decide, then look.
java
public class FlInteger {
    public static void main(String[] args) {
        System.out.println("valueOf(100) twice, same object: " + (Integer.valueOf(100) == Integer.valueOf(100)));
        System.out.println("valueOf(1000) twice, same object: " + (Integer.valueOf(1000) == Integer.valueOf(1000)));
        System.out.println("valueOf(127) twice, same object: " + (Integer.valueOf(127) == Integer.valueOf(127)));
        System.out.println("valueOf(128) twice, same object: " + (Integer.valueOf(128) == Integer.valueOf(128)));
        System.out.println("java " + System.getProperty("java.version"));
    }
}
OutputRan with eclipse-temurin:21-jdk (Java 21.0.12)
valueOf(100) twice, same object: true
valueOf(1000) twice, same object: false
valueOf(127) twice, same object: true
valueOf(128) twice, same object: false
java 21.0.12
The cache covers 127 and stops before 128.

100 and 127 return a shared object; 1000 and 128 return two new ones. The Integer.valueOf documentation guarantees a cache from -128 to 127, and the run in eclipse-temurin:21-jdk, Java 21.0.12, agrees.

The JDK's factory has the same parts as the template: the key is the number, the pool is an array of pre-built Integer objects, and an Integer is immutable, so sharing it is safe. The upper bound can be raised with the -XX:AutoBoxCacheMax option, and a run with it set to 2000 made the comparison of two 1000s true.

The same mechanism serves autoboxing, where Java turns an int into an Integer without being asked, because the compiler writes a call to Integer.valueOf. That is the route by which the cache reaches ordinary code, usually without the programmer noticing.