Through autoboxing and auto-unboxing, we can use primitive types in places where reference types are expected, and vice-versa.
To provide a concrete example, suppose we are fleshing out an implementation of a generic stack of items, with <Item>
being used as a placeholder for the type parameter passed to the class. In this context, Item
must be a reference type, but suppose we want to make a stack of primitive values (i.e., values of type int, double, char, etc.)...
To accomplish this, we can use a "wrapper type" for the primitive type in question. The following lists wrapper types for the 8 primitive data types in Java:
Primitive Type | Associated Wrapper Type |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Primitive types can be automatically cast to their associated wrapper types (this is called "Autoboxing"). Further, wrapper types can be automatically cast to their associated primitive types (this is called "Auto-unboxing")
Here's an example -- each comment shows how the compiler treats the statement on the same line:
Stack<Integer> s = new Stack<Integer>(); s.push(17); // s.push(new Integer(17)); int a = s.pop(); // int a = s.pop().intValue();
Note, objects of these wrapper types can't always be compared for equality with "==
", so one should only use wrapper types when they are needed.