Usually the compiler generates code to perform boxing and unboxing. But what does the compiler, if the boxed values are not needed? Is the (Oracle standard) compiler smart enough to optimize it away?
Take a look at this method:
public static void requireInRange(int index, Object[] array) {
if(index < 0 || index >= array.length)
throw new IndexOutOfBoundsException();
}
The only relevant information is the array.length
, so it would be useless to box each value of an array for example. Like in this code:
int[] anArray = {3, 4, 2};
requireInRange(3, anArray);
Will the compiler actually insert code for boxing each value of the array?
The compiler will reject the code because an
int[]
cannot be passed into a method that takes anObject[]
parameter.Autoboxing happens only for individual primitive values, never for entire arrays.
If in doubt, you can assume the compiler does not optimise the code. Generally it does a literal translation of the code.
Additionally, if in doubt youc an assume the JVM does a very good job of optimising the code at runtime. I wouldn't assume it makes any difference unless you have good reason (such as profiler) to suspect it is a problem.
There is no autoboxing in your code. In fact, given:
While an
int
can be autoboxed to anInteger
, anint[]
does NOT get autoboxed toInteger[]
by Java. You can write library functions to do this, but the language will not facilitate this conversion.This is in fact the source of many confusion regarding e.g.
Arrays.asList(anIntArray)
being "broken", because instead of returning aList<Integer>
, what is returned is in fact a one-elementList<int[]>
.But what about performance???
A quote from Java Language Guide/Autoboxing:
In short, whenever autoboxing happens, performance definitely takes a little bit of a hit. Certain things help to alleviate this, e.g. the caching mechanism built into these types. This is why you get the following:
What happened here is that when
0
is automatically boxed, no newInteger
instance is actually created: values in certain range is cached for autoboxing purposes, to help performance.10000
in most implementation probably falls out of this range, but some JVM implementations do allow you to specify the cache range if necessary.But I just want to get the length of the array!!!
There are many ways to facilitate your
requireInRange
to work with any type of arrays. Unfortunately working with Java's array of primitives often times mean lots of repetition. This mean providing overloads forint[]
,boolean[]
,byte[]
,Object[]
, etc separately.A more concise option is to use reflection, but this has its pluses and minuses. Generally speaking, reflection should not be the preferred solution for most scenarios.
Having said that,
java.lang.reflect.Array
does have aint getLength(Object array)
static
method that can return the length of ANY array. It's not typesafe (like most reflection mechanism are); passing a non-array compiles, but throwsIllegalArgumentException
at run-time.Related questions
java.util.Arrays
)