4.7 - Wrapper Classes

superdancer16

Introduction

Java has two categories of data types: primitives (int, double, boolean, etc.) and objects (instances of classes). Sometimes we need to treat primitive values as objects—for example, to store them in ArrayLists or use object-specific methods. Wrapper classes solve this problem by providing object versions of primitive types.

Topic 4.7 focuses on two wrapper classes: Integer (wraps int) and Double (wraps double). We'll explore how Java automatically converts between primitives and wrappers through autoboxing and unboxing, and how to parse strings into numeric values.

What are Wrapper Classes?

Wrapper classes are object types that "wrap" primitive values, allowing primitives to be treated as objects.

Each primitive type has a corresponding wrapper class:

PrimitiveWrapper Class
intInteger
doubleDouble
booleanBoolean
charCharacter

For AP Computer Science A, we focus on Integer and Double.

The Integer Class

The Integer class and Double class are part of the java.lang package. No import statement is needed—these classes are automatically available.

An Integer object is immutable, meaning once an Integer object is created, its attributes cannot be changed. The value stored inside cannot be modified.

Creating Integer Objects

Integer num1 = new Integer(42);  // Wraps the int value 42
Integer num2 = new Integer(100);

Note: The Integer(int) constructor is deprecated in newer Java versions, but you should understand it for the AP exam. Modern code uses autoboxing instead (explained below).

Integer is Immutable

Integer x = new Integer(5);
// There's no way to change x's internal value to 10
// x always contains 5 unless you reassign x to a different Integer object

This differs from mutable objects where you can call methods to change their state.

The Double Class

Works identically to Integer but wraps double values.

A Double object is immutable, meaning once a Double object is created, its attributes cannot be changed.

Double price = new Double(19.99);
Double temperature = new Double(72.5);

Autoboxing

Autoboxing is the automatic conversion that the Java compiler makes between primitive types and their corresponding object wrapper classes.

The Java compiler applies autoboxing when a primitive value is:

  • Passed as a parameter to a method that expects an object of the corresponding wrapper class
  • Assigned to a variable of the corresponding wrapper class

Examples of Autoboxing

// Autoboxing: int to Integer
int primitive = 42;
Integer wrapped = primitive;  // Automatically converts
// Autoboxing in method call
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(50);  // int 50 automatically becomes Integer

Behind the scenes, Java converts int to Integer:

Integer wrapped = Integer.valueOf(primitive);

Why Autoboxing Matters

ArrayLists can only store objects, not primitives:

// This won't work:
ArrayList<int> numbers;  // WRONG - can't use primitives
// Must use wrapper class:
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(10);  // Autoboxing converts int 10 to Integer

Unboxing

Unboxing is the automatic conversion that the Java compiler makes from the wrapper class to the primitive type.

The Java compiler applies unboxing when a wrapper class object is:

  • Passed as a parameter to a method that expects a value of the corresponding primitive type
  • Assigned to a variable of the corresponding primitive type

Examples of Unboxing

// Unboxing: Integer to int
Integer wrapped = 42;
int primitive = wrapped;  // Automatically converts
// Unboxing in arithmetic
Integer a = 10;
Integer b = 20;
int sum = a + b;  // Both unbox to int, then add

Behind the scenes, Java calls:

int primitive = wrapped.intValue();

Complete Autoboxing/Unboxing Example

ArrayList<Integer> scores = new ArrayList<Integer>();

// Autoboxing: int to Integer
scores.add(85);   // int 85 becomes Integer
scores.add(92);
scores.add(78);

// Unboxing: Integer to int
int firstScore = scores.get(0);  // Integer becomes int
int sum = 0;
for (Integer score : scores) 
{
    sum += score;  // Each Integer unboxes to int
}

double average = (double) sum / scores.size();

Parsing Strings to Numbers

Often data comes as strings (from files, user input, etc.) but we need numeric values. The Integer and Double classes provide static methods for conversion.

Integer.parseInt

The following class Integer method converts strings to integers:

static int parseInt(String s) — returns the String argument as an int.

String text = "42";
int number = Integer.parseInt(text);
System.out.println(number + 10);  // 52

Important: The string must contain a valid integer, or NumberFormatException occurs:

Integer.parseInt("123");    // OK: returns 123
Integer.parseInt("3.14");   // ERROR: not an integer
Integer.parseInt("abc");    // ERROR: not a number

Double.parseDouble

The following class Double method converts strings to doubles:

static double parseDouble(String s) — returns the String argument as a double.

String text = "3.14";
double number = Double.parseDouble(text);
System.out.println(number * 2);  // 6.28

Examples:

Double.parseDouble("19.99");   // OK: returns 19.99
Double.parseDouble("100");     // OK: returns 100.0
Double.parseDouble("2.5e3");   // OK: returns 2500.0
Double.parseDouble("hello");   // ERROR: NumberFormatException

Practical Use: Reading File Data

// File contains: "Alice,85,92,78"
String line = scan.nextLine();
String[] parts = line.split(",");

String name = parts[0];                    // "Alice"
int score1 = Integer.parseInt(parts[1]);   // 85
int score2 = Integer.parseInt(parts[2]);   // 92
int score3 = Integer.parseInt(parts[3]);   // 78

double avg = (score1 + score2 + score3) / 3.0;

Common Use Cases

Use Case 1: ArrayList of Numbers

ArrayList<Integer> ages = new ArrayList<Integer>();
ages.add(15);  // Autoboxing
ages.add(22);
ages.add(17);

int youngest = ages.get(0);  // Unboxing
for (int age : ages) 
{       // Unboxing in loop
    System.out.println(age);
}

Use Case 2: Converting String Input

// Process comma-separated numbers
String input = "10,20,30,40";
String[] tokens = input.split(",");

int sum = 0;
for (String token : tokens) 
{
    sum += Integer.parseInt(token);
}
System.out.println("Sum: " + sum);  // Sum: 100

Use Case 3: Null Values

Wrapper classes can be null, primitives cannot:

Integer score = null;  // OK - reference can be null
int value = null;      // ERROR - primitives can't be null

This is useful for representing "no value" or "missing data":

ArrayList<Integer> scores = new ArrayList<Integer>();
scores.add(85);
scores.add(null);  // Represents missing score
scores.add(92);

for (Integer score : scores) 
{
    if (score != null) // Check for missing data
    {  
        System.out.println(score);
    }
}

Wrapper Class Methods

Besides parsing, wrapper classes provide utility methods:

Integer.MAX_VALUE      // Largest int: 2147483647
Integer.MIN_VALUE      // Smallest int: -2147483648

Double.MAX_VALUE       // Largest double
Double.MIN_VALUE       // Smallest positive double

Integer a = 42;
String s = a.toString();  // Converts to "42"

Common Mistakes

Mistake 1: Confusing parse methods

// WRONG - parseInt returns int, not Integer
Integer num = Integer.parseInt("42");  // Works due to autoboxing
int value = Integer.valueOf("42");     // Works due to unboxing
// But mixing them up shows misunderstanding

Mistake 2: NullPointerException with unboxing

Integer score = null;
int value = score;  // ERROR: can't unbox null

Mistake 3: Forgetting parse methods are static

String text = "100";
// WRONG - parseInt is static, not instance method
// text.parseInt();  // Doesn't exist

// CORRECT
int num = Integer.parseInt(text);

Practice Problems