Consider these two pieces of code:
int a = 1000; int b = a + 1;
Integer a = 1000; Integer b = a + 1;
Question: Which version is more efficient?
Answer: The two versions look almost the identical, but the first version is a lot more efficient than the second one.
The second version is using a representation for the numbers that uses more space, and is relying on auto-boxing and auto-unboxing behind the scenes. In fact the second version is directly equivalent to the following code:
Integer a = Integer.valueOf(1000); // box 1000 Integer b = Integer.valueOf(a.intValue() + 1); // unbox 1000, add 1, box 1001
Comparing this to the other version that uses
int, there are clearly three extra method calls when
Integer is used. In the case of
valueOf, the calls are each going to create and initialize a new
Integer object. All of this extra boxing and unboxing work is likely to make the second version an order of magnitude slower than the first one.
In addition to that, the second version is allocating objects on the heap in each
valueOf call. While the space utilization is platform specific, it is likely to be in the region of 16 bytes for each
Integer object. By contrast, the
int version needs zero extra heap space, assuming that
b are local variables.
Another big reason why primitives are faster then their boxed equivalent is how their respective array types are laid out in memory.
If you take
Integer as an example, in the case of an
int values are contiguously laid out in memory. But in the case of an
Integer it's not the values that are laid out, but references (pointers) to
Integer objects, which in turn contain the actual
Besides being an extra level of indirection, this can be a big tank when it comes to cache locality when iterating over the values. In the case of an
int the CPU could fetch all the values in the array, into it's cache at once, because they are contiguous in memory. But in the case of an
Integer the CPU potentially has to do an additional memory fetch for each element, since the array only contains references to the actual values.
In short, using primitive wrapper types is relatively expensive in both CPU and memory resources. Using them unnecessarily is in efficient.