In addition to having lots of extra function and method calls, this
code potentially creates a bunch of objects. There are four
separate objects, holding the values 0 through 3.

Conversion from base type to object type is called boxing.
In the code above, this is achieved by the calls to
Integer.valueOf.

Conversion from object type to base type is called unboxing.
In the code above, this is achieved by the calls to
i.intValue.

We will mostly only see code boxing integers and doubles. Here is
a table summarizing the operations.

Base type

Object type

Boxing (base to object)

Unboxing (object to base)

int base = 0;

Integer object = null;

object = Integer.valueOf(base);

base = object.intValue();

double base = 0.0;

Double object = null;

object = Double.valueOf(base);

base = object.doubleValue();

Java has five additional base types, as follows.

Base type

Object type

Boxing (base to object)

Unboxing (object to base)

boolean base = false;

Boolean object = null;

object = Boolean.valueOf(base);

base = object.booleanValue();

float base = 0.0F;

Float object = null;

object = Float.valueOf(base);

base = object.floatValue();

byte base = 0;

Byte object = null;

object = Byte.valueOf(base);

base = object.byteValue();

char base = 0;

Character object = null;

object = Character.valueOf(base);

base = object.charValue();

short base = 0;

Short object = null;

object = Short.valueOf(base);

base = object.shortValue();

long base = 0L;

Long object = null;

object = Long.valueOf(base);

base = object.longValue();

Most compiled languages make an explicit distinction between object
and base types. In C# they are called values
types (declared with struct). Swift
uses fancy
compiler foo to get code that looks like python,
but runs like Java.