Skip to content
Theory · Wrappers and equality · lesson 1 of 8

Wrapper classes

What you'll learn

What you'll learn:

  • name the wrapper of every primitive and turn a string into a number with Integer.parseInt;
  • spot where the compiler boxes and unboxes a number for you, and explain why unboxing null stops the program;
  • explain why == on two Integers gives true for 127 and false for 128, and compare wrappers with equals;
  • override equals in your own class so that objects are compared by their fields.

Picture a coin and an envelope. The coin is the value itself: you hold it in your hand, and it has nothing but its face value. The envelope is a paper sleeve with a label, holding one coin inside. You put the coin into an envelope when you need to pass it somewhere that accepts only envelopes. And there may be no envelope at all, which is an answer too: "no coin yet".

In Java the primitive int is the coin: the variable holds the number itself, like the box from the variables theme. The wrapper Integer is the envelope: an object on the heap with one number inside. A variable of type Integer holds a reference to that object.

But the Integer class is not only for envelopes. Let's start with a task that comes up all the time. Numbers often reach a program as text: from the args arguments, from a file, from an input field on a website. And the text "42" is two characters, not a number:

JAVA
public class Main {
    public static void main(String[] args) {
        String text = "42";
        System.out.println(text + 1); // 421
        int n = Integer.parseInt(text);
        System.out.println(n + 1);    // 43
    }
}

Let's go line by line:

  1. text holds the characters 4 and 2, not the number forty-two.
  2. text + 1 sticks a one onto the string and prints 421.
  3. Integer.parseInt(text) reads the digits of the string and returns the number 42 of type int.
  4. n + 1 adds two numbers and prints 43.

Integer here is not a variable but a class, and parseInt is its static method. You have already met this class: the constant Integer.MAX_VALUE, the largest int value, lives in it too. It is the wrapper class for int.

Eight wrappers

A wrapper class is a class whose object holds one value of a primitive type. Each of the eight primitives has its own wrapper:

PrimitiveWrapper
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

Almost everywhere the wrapper's name is the primitive's name with a capital letter. Two exceptions are worth remembering: int → Integer and char → Character.

A wrapper is an object

You put a coin into an envelope with the method Integer.valueOf, and take it out with the method intValue:

JAVA
Integer boxed = Integer.valueOf(42);
int back = boxed.intValue();
System.out.println(back + 1); // 43
Integer score = null;
System.out.println(score);    // null

Line by line:

  1. Integer.valueOf(42) returns an Integer object with the number 42 inside, and boxed gets a reference to it.
  2. boxed.intValue() takes the number out of the object: back holds an ordinary int.
  3. back + 1 prints 43.
  4. Integer score = null;: a wrapper variable can hold null, meaning there is no envelope.
  5. System.out.println(score) prints the word null.

What is null good for? Picture the grade for an exam that has not been taken yet. An int score would hold 0, but zero is a real grade too, and you cannot tell the two cases apart. Integer score = null says it honestly: no grade yet.

A primitive cannot do that. The line int n = null; does not compile, with the error incompatible types: <null> cannot be converted to int: an int variable always holds some number.

Here the envelope picture is off. A real envelope can be opened and the coin swapped. An Integer object is sealed for good: the number in it never changes, like the characters of a string. To get another number, you take another object.

Useful wrapper methods

The wrapper classes hold tools for their type. You call them through the class name, like Integer.parseInt, with no object at all:

JAVA
double price = Double.parseDouble("2.5");
System.out.println(price * 2);         // 5.0
long big = Long.parseLong("3000000000");
System.out.println(big + 1);           // 3000000001
Integer seven = Integer.valueOf("7");
System.out.println(seven);             // 7

From a string to a number

Each numeric wrapper has its own parse method: Integer.parseInt, Long.parseLong, Double.parseDouble. The string for parseInt must be a whole integer from end to end: digits and, if needed, a - or + sign at the start. A space, a letter or a dot, and the method stops the program at run time. The number must also fit into an int: the string "3000000000" from the example is read with Long.parseLong.

valueOf or parseInt

Integer.valueOf takes a string too: Integer.valueOf("7"). The difference is in what these methods return:

  • Integer.parseInt returns the primitive int;
  • Integer.valueOf returns an Integer object.

Constants

The limits of the integer types live in the constants of their wrappers: Integer.MIN_VALUE and Integer.MAX_VALUE, Long.MIN_VALUE and Long.MAX_VALUE.

Why wrappers exist

Interviewers often ask: why does Java have wrappers when it has primitives? A good answer has three parts:

  • a wrapper turns a number into an object, and many parts of the standard library, such as collections, store only objects;
  • a wrapper variable can hold null, that is, "no value";
  • the wrapper class holds the type's tools: parseInt, valueOf, MAX_VALUE.

Common mistake

A price is read from text with parseInt:

JAVA
String priceText = "3.5";
int price = Integer.parseInt(priceText); // ✗
TEXT
Exception in thread "main" java.lang.NumberFormatException: For input string: "3.5"

The program compiles: the compiler does not look inside strings. parseInt finds the problem at run time: an integer is not written with a dot. The method throws a NumberFormatException and names the string it could not read. A fractional number is read with Double.parseDouble, and a string with spaces around it is first cleaned with strip().

Key points

  • Every primitive has a wrapper class: int → Integer, char → Character, and the rest use the same name with a capital letter.
  • A wrapper is an immutable object holding one value; a wrapper variable holds a reference and can hold null.
  • Integer.parseInt turns a string into an int, and Integer.valueOf turns it into an Integer object.
  • A string that is not a number from end to end, such as "3.5", gives a NumberFormatException at run time.