Primitive | Boxed Type | Memory Size of primitive / boxed |
---|---|---|
boolean | Boolean | 1 byte / 16 bytes |
byte | Byte | 1 byte / 16 bytes |
short | Short | 2 bytes / 16 bytes |
char | Char | 2 bytes / 16 bytes |
int | Integer | 4 bytes / 16 bytes |
long | Long | 8 bytes / 16 bytes |
float | Float | 4 bytes / 16 bytes |
double | Double | 8 bytes / 16 bytes |
Boxed objects always require 8 bytes for type and memory management, and because the size of objects is always a multiple of 8, boxed types all require 16 bytes total. In addition, each usage of a boxed object entails storing a reference which accounts for another 4 or 8 bytes, depending on the JVM and JVM options.
In data-intensive operations, memory consumption can have a major impact on performance. Memory consumption grows even more when using arrays: a float[5]
array will require only 32 bytes; whereas a Float[5]
storing 5 distinct non-null values will require 112 bytes total (on 64 bit without compressed pointers, this increases to 152 bytes).
The space overheads of the boxed types can be mitigated to a degree by the boxed value caches. Some of the boxed types implement a cache of instances. For example, by default, the Integer
class will cache instances to represent numbers in the range -128
to +127
. This does not, however, reduce the additional cost arising from the additional memory indirection.
If you create an instance of a boxed type either by autoboxing or by calling the static valueOf(primitive)
method, the runtime system will attempt to use a cached value. If your application uses a lot of values in the range that is cached, then this can substantially reduce the memory penalty of using boxed types. Certainly, if you are creating boxed value instances "by hand", it is better to use valueOf
rather than new
. (The new
operation always creates a new instance.) If, however, the majority of your values are not in the cached range, it can be faster to call new
and save the cache lookup.