Boxing Conversion in J2SE 5.0 Blog

Version 2



    The What and Why of Boxing Conversion
    Boxing/Unboxing Conversions
    Method Invocation Conversion
    Performance Issues
    Immutable Objects

    Last year, Sun released its latest version of Java, J2SE 5.0, with lots of new features. One of them is the autoboxing conversions for primitives and wrapper objects. This article gives some insight about what boxing conversion in Java is, and how it is used in real-world programming. I will present the meaning of autoboxing and a few programming techniques.

    The What and Why of Boxing Conversion

    Boxing is a way to wrap primitive types with objects so that they can be used like objects. For example, theInteger class wraps the int primitive type in Java. Similarly, unboxing is a way to convert object types back to primitive types.

    From the programmer's perspective, reducing code size and improving performance is an challenging job. The need to explicitly convert data from primitives to object references arises frequently and is often burdensome. Another annoying problem with using traditional casting techniques is that it clutters up the code. J2SE 5.0's boxing/unboxing feature can eliminate these problems.

    Boxing/Unboxing Conversions

    Let's look into the basic syntax of boxing/unboxing conversions:


    Consider the following code fragment:

     // Assigning primitive type to wrapper type Integer iWrapper = 10;

    Prior to J2SE version 5.0, this code would not compile, since the Integer variable iWrapper expects an object assignment, and 10 is an intprimitive. It will work if you modify the above code like this:

     // Assigning primitive type to wrapper type Integer iWrapper = new Integer(10);

    This type of conversion occurs frequently throughout a program. It is annoying to have to do this repeatedly. But if we use the J2SE 5.0 compiler, the conversion will be done for us. This means the programmer can reduce the size of his or her source code by avoiding unnecessary conversions. Of course, the Java Virtual Machine (JVM) still does internal conversions back and forth between primitives and objects, but at least the source is cleaner.


    Unboxing is opposite of boxing: converting from object types to primitive types. Consider the following code fragment:

     // Assigning object to primitive. public void intMethod(Integer iWrapper){ int iPrimitive = iWrapper.intValue(); }

    In J2SE 1.4 and earlier, we are forced to perform explicit conversions. It would be easier if there were no conversions at all. J2SE 5.0 gives you the solution. Here's the modified version of the above code fragment:

     // Assigning object to primitive. public void intMethod(Integer iWrapper){ int iPrimitive = iWrapper; }

    It looks good, doesn't it? No more conversion with wrapper objects and primitive objects!

    Method Invocation Conversion

    Autoboxing and unboxing can make method overloading interesting. Consider the two overloaded methods shown here:

     public static void testMethod(long lVar){ System.out.println("Long"); } public static void test(Integer iVar){ System.out.println("Integer"); } 

    Here autoboxing plays a different role, choosing a most-specific method when more than one method is applicable for method invocation.

    If you call testMethod() with a primitivelong parameter, then the firsttestMethod() is used. If you calltestMethod() with an Integer object parameter, then the second testMethod() is used. There is nothing new there.

    But what happens if you call testMethod() with anint parameter? In J2SE 1.4 and below, theint is promoted to a long and the firsttestMethod() is used. With autoboxing, it is acceptable that the int could be boxed into anInteger type and the second testMethod()used. That might even be what you want to happen--it might make more sense to convert an int to anInteger than to promote it to a long.

    While arguably reasonable, that is not what happens. The general rule is, for compatibility reasons, the same behavior that applied in pre-5.0 versions must continue to hold. The reason is that existing code cannot suddenly start behaving differently when compiled and run under 5.0.

    Consider the following code snippet:

     public void testMethod(Integer i){ //statements } Public void testMethod(int i){ //statements }

    When we invoke the method with an int as the parameter:


    obviously, testMethod (int i) is called. Because when we invoke a method, the compiler will first try to use normal method invocation, without autoboxing. if it fails to find a matching method signature, then it will box the values and try to find a matching method.

    Consider the following code:

     Public void floatMethod(Float f){ //statements }

    What do you think will happen when we use the following invocation?


    Don't be surprised when the compiler rejects your code. Here, the widening conversion has not taken place. The compiler searches for testMethod() with an int argument. If it doesn't find one, it autoboxes and searches for atestMethod() that takes an Integerargument. A programmer might expect it to compile, expecting the compiler to employ widening conversions to convert theint to a float and then autoboxing thefloat primitive to its wrapper object. But that's not what the compiler does, and this confuses many programmers.

    Performance Issues

    A few experiments have shown that autoboxing can be inefficient, and can give you a false sense of efficiency. What may look like an efficient use of primitive data types at the source-code level could well turn out to be a very inefficient use of primitive data wrapper types when it comes to the runtime.

    Look into the following code:

     import java.util.*; public class AutoBoxingPerformanceTest{ public static void main(String args[]){ long time1 = 0; long time2 = 0; List<Integer> listValues = new ArrayList<Integer>(); int arrValues[] = new int[1000000]; /* Inserting values into List and Array */ for(int i =0;i<1000000;i++){ listValues.add(i); arrValues[i]=i; } /* Reterive the values from collection objects and do the multiplication*/ time1 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ listValues.set(i,listValues.get(i)*10); } time2 = System.currentTimeMillis(); System.out.println("AutoBoxing with Collection : "+(time2-time1)+"ms"); /* Reterive the values from arrays and do the multiplication*/ time1 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ arrValues[i]=arrValues[i]*10; } time2 = System.currentTimeMillis(); System.out.println("Using an Array : "+(time2-time1)+"ms"); } }

    The output is:

    AutoBoxing with Collection : 421ms Using an Array : 0ms

    When we are using the boxing conversions within a loop, it affects the performance of a program. The above program is an example of how performance differs when we use boxing conversion back and forth between primitives and wrappers from a collection, versus normal arithmetic operation from an intarray.

    In this example, we first put a number of primitive values into an collection and an array. Then we do an arithmetic operation on each value of the collection or array. The array loop performs much better than the collection loop, since collections need to perform boxing conversions before doing arithmetic multiplication on their contents.

    We have to be aware when we may be doing unnecessary things that could impact performance, such as autoboxing when we should not.

    The important point we must consider is that autoboxing doesn't reduce object creation, but it reduces code complexity. A good rule of thumb is to use primitive types where there is no need for objects, for two reasons:

    • Primitive types will not be slower than their corresponding wrapper types, and may be a lot faster.
    • There can be some unexpected behavior involving ==(compare references) and .equals() (compare values).

    Immutable Objects

    Consider the following code fragment:

     Integer i1 = 100; Integer i2 = 100; Integer i3 = 1000; Integer i4 = 1000; System.out.println(i1==i2); System.out.println(i3==i4);

    Can you guess what will be printed on the screen? If your answer is false--well, you're wrong.

    In this case, J2SE 5.0 works differently. Certain ranges of values are stored as immutable objects by the Java Virtual Machine. So, in this case, the output is:

    true false

    Normally, when the primitive types are boxed into the wrapper types, the JVM allocates memory and creates a new object. But for some special cases, the JVM reuses the same object.

    The following is the list of primitives stored as immutable objects:

    • boolean values true andfalse
    • All byte values
    • short values between -128 and 127
    • int values between -128 and 127
    • char in the range \u0000 to\u007F


    While there is much to like about autoboxing, it does create a few problems. Here are some scenarios where it will clutter your programming.

    Consider the following program:

     public class AutoBoxingTest{ public static void main(String args[]){ Integer iVar1 = new Integer(10); Integer iVar2 = 10; System.out.println("Lessthan Check : " + (iVar1 <= iVar2)); System.out.println("Greater than Check : " + (iVar1 >= iVar2)); System.out.println("Equality Check : " + (iVar1 == iVar2)); } }

    The output is:

     Less than Check : true Greater than Check : true Equality Check : false

    When we are working with comparison operators, the boxing conversion works a little differently. The output for the above program shows that, The operators <,<=, >, and >= work fine. But when we come to the equals operator, ==, the JVM interprets that as the operator for object equality, rather than unboxing ivar2 and testing mathematical equality.


    Autoboxing unclutters your code, but comes with important considerations in terms of performance and sometimes unexpected behavior. This new feature gives programmers more flexibility and can save lots of time. Hopefully, autoboxing will reduce the more number of programming errors in the future by avoiding the conversions back and forth between primitives and objects.