Here’s a fact that you may not know. When you auto-box integral primitives (
long) to their respective wrapper classes (
Long), the wrapper classes cache all values from
+127. These values are later used by the
valueOf() methods to give better performance than using a constructor.
Let’s use an example of auto-boxing an
int into an
Integer a = 33;
Behind the scenes when the compiler generates code to auto-box the
int, it uses the static
Integer.valueOf() method. The
valueOf() method first checks the cache. If the value to be auto-boxed falls in the range
+127, then it returns the previously-created cached
Integer. Otherwise it creates a new
Integer object. This yields better performance for commonly used values.
Let’s look at a code snippet:
Integer a = 33; // same as Integer a = Integer.valueOf(33); Integer b = 33; Integer c = new Integer (33); System.out.printf("a == b : %b%n", a==b); System.out.printf("a == c : %b%n", a==c); System.out.printf("a.equals(b) : %b%n", a.equals(b)); System.out.printf("a.equals(c) : %b%n", a.equals(c));
b with the
== operator returns
a == c returns
b refer to the same object in the cache, while
c refers to a new
Integer object on the heap. Using the
equals() method will always return
Now let’s change the values of
c to the following:
Integer a = 133; Integer b = 133; Integer c = new Integer (133); System.out.printf("a == b : %b%n", a==b); System.out.printf("a == c : %b%n", a==c); System.out.printf("a.equals(b) : %b%n", a.equals(b)); System.out.printf("a.equals(c) : %b%n", a.equals(c));
a == b returns
false because they refer to different objects. This is because their values are outside the range of the cache limits. New
Integer objects have been created for each value when auto-boxed.
Changing the Cache Limit
We can change the upper cache limit, but not the lower limit. When starting the JVM, we can use either of two options (the
xxx is the value you want for the upper limit):
java -Djava.lang.Integer.IntegerCache.high=xxx MyClass
java -XX:AutoBoxCacheMax=xxx MyClass
-D option will always work, but the
-XX: option is non-standard, and may not be supported by the compiler you are using.
Why do you have to know this?
There are practical implications of caching other than just performance. Not knowing about the cache can lead to unexpected behaviour when comparing wrapped integral numbers which may take you a lot of time and effort to track down. And as an added knowledge bonus, it’s also a common question in certification exams.