Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance impact of autoboxing

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?

like image 681
deamon Avatar asked Aug 07 '10 13:08

deamon


People also ask

What is the major advantage of Autoboxing?

Autoboxing and unboxing lets developers write cleaner code, making it easier to read. The technique lets us use primitive types and Wrapper class objects interchangeably and we do not need to perform any typecasting explicitly.

What happens in Autoboxing?

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.

What is the difference between boxing and Autoboxing?

Boxing is the mechanism (ie, from int to Integer ); autoboxing is the feature of the compiler by which it generates boxing code for you. For instance, if you write in code: // list is a List<Integer> list.

Who is responsible for performing Autoboxing and unboxing in Java?

Who is responsible for performing Autoboxing and unboxing in java? Java compiler is responsible for making such conversions. Before java 5 we used to write such code for performing Autoboxing.


2 Answers

There is no autoboxing in your code. In fact, given:

public static void requireInRange(int index, Object[] array) {
   ...
}

int[] anArray = {3, 4, 2};
requireInRange(3, anArray); // DOES NOT COMPILE!!!

While an int can be autoboxed to an Integer, an int[] does NOT get autoboxed to Integer[] 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 a List<Integer>, what is returned is in fact a one-element List<int[]>.


But what about performance???

A quote from Java Language Guide/Autoboxing:

It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code. An Integer is not a substitute for an int; autoboxing and unboxing blur the distinction between primitive types and reference types, but they do not eliminate it.

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:

    System.out.println(
        ((Integer) 0) == ((Integer) 0)
    );
    // true

    System.out.println(
        ((Integer) 10000) == ((Integer) 10000)
    );
    // false (implementation-specific)

What happened here is that when 0 is automatically boxed, no new Integer 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 for int[], 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 a int 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 throws IllegalArgumentException at run-time.

Related questions

  • Managing highly repetitive code and documentation in Java - ("inspired" by java.util.Arrays)
like image 94
polygenelubricants Avatar answered Sep 21 '22 04:09

polygenelubricants


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 an Object[] parameter.

Autoboxing happens only for individual primitive values, never for entire arrays.

like image 41
Michael Borgwardt Avatar answered Sep 23 '22 04:09

Michael Borgwardt