10.2. Wrapper Classes

In the previous section, we saw that we can create a generic ShippingContainer class. We also saw that the generic type parameter can be replaced with any reference type. At this point, you may be wondering how we could create a ShippingContainer object and use one of the primitive data types for the type argument (the data type of the contents of the container).

In Java, there is a wrapper class for all 8 of the primitive types (byte, short, int, long, float, double, char, and boolean). These wrapper classes essentially "wrap" the primitive value into an object allowing us to use them as we would their primitive counterparts.

Table 10.1 Primitive Types and their Corresponding Wrapper Classes

Primitive Type

Wrapper Class

byte

Byte

short

Short

int

Integer

long

Long

float

Float

double

Double

boolean

Boolean

char

Character

10.2.1. Looking Under the Hood

Let's look at a memory map diagram to better understand the difference between an int and an Integer.

When we declare x to be an int, the variable directly stores the value 17:

Listing 10.1 Declaring a primitive type integer
int x = 17;
Code visualization diagram for java/generics/wrapper-classes:46 (end of main)

Declaring a primitive type integer [code listing] [download] [open]

In the following independent example, x is declared as an Integer. The Integer.valueOf(17) method call returns with a reference value referring to an Integer object containing 17. The variable x stores that reference value:

Listing 10.2 Declaring an Integer reference variable
Integer x = Integer.valueOf(17);
Code visualization diagram for java/generics/wrapper-classes:57 (end of main)

Declaring an Integer reference variable [code listing] [download] [open]

The difference is subtle, but extremely important. Using the wrapper classes instead of the primitive data types gives us a workaround that allows us to use primitive values in our generic classes.

10.2.2. Shipping Container Examples

These examples will not compile because they use a primitive data type as the type argument:

Listing 10.3 These will not compile
1ShippingContainer<int> intContainer = new ShippingContainer<int>(17);
2ShippingContainer<char> charContainer = new ShippingContainer<char>('c');

However, if we use the wrapper classes, the code will compile:

Listing 10.4 These will compile
1ShippingContainer<Integer> intContainer = new ShippingContainer<Integer>(17);
2ShippingContainer<Character> charContainer = new ShippingContainer<Character>('c');