Integer i = 3;
i = i + 1;
Integer j = i;
j = i + j;
How many objects are created as a result of the statements in the sample code above and why? Is there any IDE in which we can see how many objects are created (maybe in a debug mode)?
Integer i = 3;
i = i + 1;
Integer j = i;
j = i + j;
How many objects are created as a result of the statements in the sample code above and why? Is there any IDE in which we can see how many objects are created (maybe in a debug mode)?
The answer, surprisingly, is zero.
All the Integer
s from -128 to +127 are pre-computed by the JVM.
Your code creates references to these existing objects.
The strictly correct answer is that the number of Integer
objects created is indeterminate. It could be between 0 and 3, or 2561 or even more2, depending on
int
values runs before it4.The Integer
values for -128 to 127 are not strictly required to be precomputed. In fact, JLS 5.1.7 which specified the Boxing conversion says this:
If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1) ... then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
Two things to note:
Even the javadoc for Integer.valueof(int)
does not specify that the results are cached eagerly.
If we examine the Java SE source code for java.lang.Integer
from Java 6 through 8, it is clear that the current Java SE implementation strategy is to precompute the values. However, for various reasons (see above) that is still not enough to allow us to give a definite answer to the "how many objects" question.
1 - It could be 256 if execution of the above code triggers class initialization for Integer
in a version of Java where the cache is eagerly initialized during class initialization.
2 - It could be even more, if the cache is larger than the JVM spec requires. The cache size can be increased via a JVM option in some versions of Java.
3 - In addition to the platform's general approach to implementing boxing, a compiler could spot that some or all of the computation could be done at compile time or optimized it away entirely.
4 - Such code could trigger either lazy or eager initialization of the integer cache.
Integer
objects are precomputed in the class initializer of java.lang.Integer.IntegerCache
but the initialization of that class is triggered by its first use so unless the JRE uses such boxed values itself before entering the main
method (in my test it didn’t), the first boxing of a value inside that range will trigger the initialization. So it’s not correct to say that no Integer
objects are created as in fact 256 Integer
objects are created while executing the main
method. –
Moke Integer
objects. Or it may elide the entire operation, if i
and j
are never used afterwards. A different JVM implementation could represent certain boxed values by storing int
values inside of pointers to address ranges outside the heap without any objects… –
Moke null
reference test, which you need anyway (if >0
traverse, otherwise it’s either null
or off-heap)… –
Moke >2GB
. –
Moke First of all: The answer you are looking for is 0
, as others already mentioned.
But let's go a bit deeper. As Stephen menthioned it depends on the time you execute it. Because the cache is actually lazy initialized.
If you look at the documentation of java.lang.Integer.IntegerCache:
The cache is initialized on first usage.
This means that if it is the first time you call any Integer you actually create:
From the second time on you call them, you create 0 Objects.
Things get more funny once you make the numbers a bit higher. E.g. by the following example:
Integer i = 1500;
Valid options here are: 0, 1 or any number between 1629 to 2147483776 (this time only counting the created Integer-values. Why? The answer is given in the next sentence of Integer-Cache definition:
The size of the cache may be controlled by the -XX:AutoBoxCacheMax= option.
So you actually can vary the size of the cache which is implemented.
Which means you can reach for above line:
Keep in mind: This is only guaranteed on Oracle / Open JDK (i checked Version 7 and 8)
As you can see the completely correct answer is not so easy to get. But just saying 0
will make people happy.
PS: using the menthoned parameter can make the following statement true: Integer.valueOf(1500) == 1500
The compiler unboxes the Integer
objects to int
s to do arithmetic with them by calling intValue()
on them, and it calls Integer.valueOf
to box the int
results when they are assigned to Integer
variables, so your example is equivalent to:
Integer i = Integer.valueOf(3);
i = Integer.valueOf(i.intValue() + 1);
Integer j = i;
j = Integer.valueOf(i.intValue() + j.intValue());
The assignment j = i;
is a completely normal object reference assignment which creates no new objects. It does no boxing or unboxing, and doesn't need to as Integer
objects are immutable.
The valueOf
method is allowed to cache objects and return the same instance each time for a particular number. It is required to cache ints −128 through +127. For your starting number of i = 3
, all the numbers are small and guaranteed to be cached, so the number of objects that need to be created is 0. Strictly speaking, valueOf
is allowed to cache instances lazily rather than having them all pre-generated, so the example might still create objects the first time, but if the code is run repeatedly during a program the number of objects created each time on average approaches 0.
What if you start with a larger number whose instances will not be cached (e.g., i = 300
)? Then each valueOf
call must create one new Integer
object, and the total number of objects created each time is 3.
(Or, maybe it's still zero, or maybe it's millions. Remember that compilers and virtual machines are allowed to rewrite code for performance or implementation reasons, so long as its behavior is not otherwise changed. So it could delete the above code entirely if you don't use the result. Or if you try to print j
, it could realize that j
will always end up with the same constant value after the above snippet, and thus do all the arithmetic at compile time, and print a constant value. The actual amount of work done behind the scenes to run your code is always an implementation detail.)
You can debug the Integer.valueOf(int i) method to find out it by yourself. This method is called by the autoboxing process by the compiler.
© 2022 - 2024 — McMap. All rights reserved.