Home : Course Map : Chapter 3 : Java :
Autoboxing/Unboxing of Wrappers
JavaTech
Course Map
Chapter 3

Introduction
Class Definition
Data Fields
Methods
Constructors
Instantiation
  
Demo 1
  Demo 2
Static Members
  Demo 3

Value&Reference
  Demo 4
Overloading
   Demo 5
Wrappers 
  Demo 6
Autobox/Unbox
   Demo 7
Arrays
  Demo 8
Exceptions
Exercises

    Supplements
MoreAboutObjects
Creating Types

Classes,Objs&JVM

Java OOP vs C++
Garbage Collection
     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

In the previous section on wrapper classess for primitive type values, we discussed how to create an instance of a wrapper from a primitive and conversely, how to obtain the primitive value held by the wrapper. This involves a a certain amount of clumsy code.

For example, creating a Float object from a float primitive is straightforward:

  float primitive_float = 3.0f;
  Float wrapper_float = new Float (primitive_float);

Going the other direction, however, requires explicitly calling the floatValue() method on the Float object:

  float primitive_float = wrapper_float.floatValue ();

If you are dealing with a lot of instances of wrappers and conversions, you will thus need to deal with a lot of method invocations.

In J2SE 5.0, however, the code to create the wrapper object allows for this much simpler form:

  Float wrapper_float = primitive_float;

Here, the "wrapping" is done automatically! There is no need to explicitly call the Float constructor. This "wrapping" is called "autoboxing" in the sense that the primitive value is automatically "boxed up" into the wrapper object. Autoboxing is available for all the primitive/wrapper types.

Going the other way, from object type to primitive, is just as simple:

  Integer wrapper_integer = 5; // primitive 5 autoboxed into an Integer
  int primitive_int = wrapper_integer; // automatic unboxing Integer into int

These shortcuts simplify coding and reduce errors in J2SE 5.0. For example, they can even be used in loop control and incrementing and decrementing operations. For a contrived example, consider adding all the integers from 1 to 100 as shown in the following program:

BoxApplet.java
(Output goes to browser's Java console.)

public class BoxApplet extends java.applet.Applet
{
  public void init () {
    int MAX = 100;       // a primitive int type
    Integer counter = 1; // an Integer type
    Integer sum = 0;     // ditto
    while (true) {
      sum += counter;
      if (counter == MAX) break;
      counter++;
    }
    System.out.println ("counter is now " + counter);
    System.out.println ("sum is now " + sum);
    System.out.println ("MAX*(MAX+1)/2 is " + MAX*(MAX+1)/2);
  } // init

  // Paint message in Applet window.
  public void paint (java.awt.Graphics g) {
     g.drawString ("BoxApplet", 20, 20);
  }
} // class BoxApplet

Application version:
BoxApp.java

 

There is a lot of hidden autoboxing and unboxing going on in this simple-looking code. First, the Integer types counter and sum are autoboxed from the primitive values 1 and 0. Then, in the loop, they are unboxed to primitive values so the += operation can be applied and then reboxed to their "native" Integer types.

To do the == comparison counter is unboxed so it can be compared with the int type MAX. If the break does not apply, then counter is unboxed, operated on with ++, and then reboxed.

Autoboxing and unboxing work in a for loop as well:

  Integer sum = 0;
  for  (Integer counter=1; counter < MAX; counter++) {
        sum += counter;
  }

Note that both of these loops are likely to perform very slowly with all these autoboxing and unboxing operations. An optimizing compiler might be able to avoid some of the autoboxing and unboxing operations, but in general you should do long looping operations with primitive types unless there is a very good reason to use a wrapper type.

Autoboxing and unboxing also work with Boolean and boolean types. For example,

  boolean one = true; // nothing new here
  Boolean two = true; // autoboxing of primitive 'true' to Boolean type
  if (one && two) // auto unboxing do_something ();

Before 5.0, the if, while, and do-while statements (see Chapter 2) all expected boolean expressions. Through the use of unboxing, those flow control statements now also accept expressions that evaluate to Boolean types.

Similarly, the old switch statement expects a byte, short, int, or char type in Java 1.4 and below. With the addition of autoboxing in 5.0, switch now also accepts Byte, Short, Integer, and Character types.

Where autoboxing and unboxing become particularly useful is with the insertion and retrieval of primitive values into and out of object containers like Vector and ArrayList (see Chapter 10). Since the container classes only accept objects, not primitives, prior to J2SE 5.0 it was necessary to convert primitives to wrapper object types for insertion and to convert wrapper objects back to primitives after retrieval. Autoboxing and unboxing now make these operations almost transparent.

With the additional new generics feature in 5.0, using primitives with container objects is even simpler. We postpone that discussion until we discuss the new generics feature in Chapter 10.

Autoboxing and Overloading

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

  long method1 (long l) { return l+1; }
  long method1 (Integer i) { return i+2; }

If you call method1() with a primitive long parameter, then the first method1() is used. If you call method1() with an Integer object parameter, then the second method1() is used. There is nothing new there. But what happens if you call method1() with an int parameter? In J2SE 1.4 and below, the int is promoted to a long and the first method1() is used. With autoboxing, it is conceivable that the int could be boxed into an Integer type and the second method1() used. That might even be what you want to happen - it might make more sense to convert an int to an Integer 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.

We would suggest that an even better rule is to realize that using overloads like this is confusing and potentially asking for trouble. There is little reason to write such obfuscated code.

References & Web Resources


Latest update: Nov. 17, 2004

           Tech
OOP in Tech Apps
Complex Number
Histogram Class
  Demo
More Wrappers

           Physics
OOP in Physics
Particle Class
Root Finding
  Demo 1
Newton Methods
  Demo 2
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.