Section 1.2. Boxing and Unboxing


1.2. Boxing and Unboxing

Recall that every type in Java is either a reference type or a primitive type. A reference type is any class, instance, or array type. All reference types are subtypes of class Object, and any variable of reference type may be set to the value null. As shown in the following table, there are eight primitive types, and each of these has a corresponding library class of reference type. The library classes are located in the package java.lang.

Primitive

Reference

byte

Byte

short

Short

int

Integer

long

Long

float

Float

double

Double

bool

Boolean

char

Character


Conversion of a primitive type to the corresponding reference type is called boxing and conversion of the reference type to the corresponding primitive type is called unboxing.

Java with generics automatically inserts boxing and unboxing coercions where appropriate. If an expression e of type int appears where a value of type Integer is expected, boxing converts it to new Integer(e) (however, it may cache frequently occurring values). If an expression e of type Integer appears where a value of type int is expected, unboxing converts it to the expression e.intValue(). For example, the sequence:

 List<Integer> ints = new ArrayList<Integer>(); ints.add(1); int n = ints.get(0); 

is equivalent to the sequence:

 List<Integer> ints = new ArrayList<Integer>(); ints.add(new Integer(1)); int n = ints.get(0).intValue(); 

In practice, the compiler will arrange for the value of new Integer(1) to be cached, as we explain shortly.

Here, again, is the code to find the sum of a list of integers, conveniently packaged as a static method:

 public static int sum (List<Integer> ints) {   int s = 0;   for (int n : ints) { s += n; }   return s; } 

Why does the argument have type List<Integer> and not List<int>? Because type parameters must always be bound to reference types, not primitive types. Why does the result have type int and not Integer? Because result types may be either primitive or reference types, and it is more efficient to use the former than the latter. Unboxing occurs when each Integer in the list ints is bound to the variable n of type int.

We could rewrite the method, replacing each occurrence of int with Integer:

 public static Integer sumInteger(List<Integer> ints) {   Integer s = 0;   for (Integer n : ints) { s += n; }   return s; } 

This code compiles but performs a lot of needless work. Each iteration of the loop unboxes the values in s and n, performs the addition, and boxes up the result again. With Sun's current compiler, measurements show that this version is about 60 percent slower than the original.

Look Out for This! One subtlety of boxing and unboxing is that == is defined differently on primitive and on reference types. On type int, it is defined by equality of values, and on type Integer, it is defined by object identity. So both of the following assertions succeed using Sun's JVM:

 List<Integer> bigs = Arrays.asList(100,200,300); assert sumInteger(bigs) == sum(bigs); assert sumInteger(bigs) != sumInteger(bigs);  // not recommended 

In the first assertion, unboxing causes values to be compared, so the results are equal. In the second assertion, there is no unboxing, and the two method calls return distinct Integer objects, so the results are unequal even though both Integer objects represent the same value, 600. We recommend that you never use == to compare values of type Integer. Either unbox first, so == compares values of type int, or else use equals to compare values of type Integer.

A further subtlety is that boxed values may be cached. Caching is required when boxing an int or short value between -128 and 127, a char value between '\u0000' and '\u007f', a byte, or a boolean; and caching is permitted when boxing other values. Hence, in contrast to our earlier example, we have the following:

 List<Integer> smalls = Arrays.asList(1,2,3); assert sumInteger(smalls) == sum(smalls); assert sumInteger(smalls) == sumInteger(smalls);  // not recommended 

This is because 6 is smaller than 128, so boxing the value 6 always returns exactly the same object. In general, it is not specified whether boxing the same value twice should return identical or distinct objects, so the inequality assertion shown earlier may either fail or succeed depending on the implementation. Even for small values, for which == will compare values of type Integer correctly, we recommend against its use. It is clearer and cleaner to use equals rather than == to compare values of reference type, such as Integer or String.




Java Generics and Collections
Java Generics and Collections
ISBN: 0596527756
EAN: 2147483647
Year: 2006
Pages: 136

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net