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.

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.

Declaring a primitive type integer
int x = 17;

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

  +----+
x | 17 |
  +----+

However, things look different under the hood when we were to declare x as an Integer:

Integer x = new Integer(17);

Instead of storing the value 17 directly, x now stores a reference to an object that contains the value 17:

  +--+     +----------+
s | -|----◆|    17    |
  +--+     |          |
           +----------+

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:

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:

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