Wrapper Classes in Java

1. Overview

As the name suggests, wrapper classes are objects encapsulating primitive Java types.

Each Java primitive has a corresponding wrapper:

  • boolean, byte, short, char, int, long, float, double 
  • Boolean, Byte, Short, Character, Integer, Long, Float, Double

These are all defined in the java.lang package, hence we don’t need to import them manually.

2. Wrapper Classes

“What’s the purpose of a wrapper class?”. It’s one of the most common Java interview questions.

Basically, generic classes only work with objects and don’t support primitives. As a result, if we want to work with them, we have to convert primitive values into wrapper objects.

For example, the Java Collection Framework works with objects exclusively. Long back when (prior to Java 5, almost 15 years back) there was no autoboxing and we, for example, couldn’t simply call add(5) on a collection of Integers.

At that time, those primitive values needed to be manually converted to corresponding wrapper classes and stored in collections.

Today, with autoboxing, we can easily do ArrayList.add(101) but internally Java converts the primitive value to an Integer before storing it in the ArrayList using the valueOf() method.

3. Primitive to Wrapper Class Conversion

Now the big question is: how do we convert a primitive value to a corresponding wrapper class e.g. an int to Integer or a char to Character?

Well, we can either use constructor or static factory methods to convert a primitive value to an object of a wrapper class.

As of Java 9, however, constructors for many boxed primitives such as Integer or Long have been deprecated.

So it’s highly recommended to only use the factory methods on new code.

Let’s see an example of converting an int value to an Integer object in Java:

Integer object = new Integer(1);

Integer anotherObject = Integer.valueOf(1);

The valueOf() method returns an instance representing the specified int value.

It returns cached values which makes it efficient. It always caches values between -128 to 127 but can also cache other values outside this range.

Similarly, we can also convert boolean to Boolean, byte to Byte, char to Character, long to Long, float to Float, and double to Double. Though if we have to convert String to Integer then we need to use parseInt() method because String isn’t a wrapper class.

On the other hand, to convert from a wrapper object to a primitive value, we can use the corresponding method such as intValue(), doubleValue() etc:

int val = object.intValue();

A comprehensive reference can be found here.

4. Autoboxing and Unboxing

In the previous section, we showed how to manually convert a primitive value to an object.

After Java 5, this conversion can be done automatically by using features called autoboxing and unboxing.

“Boxing” refers to converting a primitive value into a corresponding wrapper object. Because this can happen automatically, it’s known as autoboxing.

Similarly, when a wrapper object is unwrapped into a primitive value then this is known as unboxing.

What this means in practice is that we can pass a primitive value to a method which expects a wrapper objector assign a primitive to a variable which expects an object:

List<Integer> list = new ArrayList<>();
list.add(1); // autoboxing

Integer val = 2; // autoboxing

In this example, Java will automatically convert the primitive int value to the wrapper.

Internally, it uses the valueOf() method to facilitate the conversion. For example, the following lines are equivalent:

Integer value = 3;

Integer value = Integer.valueOf(3);

Though this makes conversion easy and codes more readable, there are some cases where we shouldn’t use autoboxing e.g. inside a loop.

Similar to autoboxing, unboxing is done automatically when passing an object to a method that expects a primitive or when assigning it to a primitive variable:

Integer object = new Integer(1); 
int val1 = getSquareValue(object); //unboxing
int val2 = object; //unboxing

public static int getSquareValue(int i) {
    return i*i;
}

Basically, if we write a method that accepts a primitive value or wrapper object, we can still pass both values to them. Java will take care of passing the right type e.g. primitive or wrapper depending upon context.

5. Conclusion

In this quick tutorial, we talked about wrapper classes in Java, as well as the mechanism of autoboxing and unboxing.

Related posts:

Hướng dẫn Java Design Pattern – Abstract Factory
The Registration API becomes RESTful
Java Program to Implement Skew Heap
Check If a File or Directory Exists in Java
Spring Security Custom AuthenticationFailureHandler
A Comparison Between Spring and Spring Boot
Java Program to Implement Multi-Threaded Version of Binary Search Tree
Java Program to Find the Nearest Neighbor Using K-D Tree Search
Introduction to Apache Commons Text
Spring Boot - Enabling HTTPS
Java Program to Check Cycle in a Graph using Graph traversal
Logout in an OAuth Secured Application
Convert Hex to ASCII in Java
Stack Memory and Heap Space in Java
Java Program to Create a Minimal Set of All Edges Whose Addition will Convert it to a Strongly Conne...
Java Program to Check if a Given Set of Three Points Lie on a Single Line or Not
Introduction to the Functional Web Framework in Spring 5
Java Program to Implement Hopcroft Algorithm
Quick Intro to Spring Cloud Configuration
New Features in Java 12
Introduction to the Java NIO2 File API
Calling Stored Procedures from Spring Data JPA Repositories
Converting Java Date to OffsetDateTime
Java Program to Implement Shunting Yard Algorithm
Java Program to Implement Graham Scan Algorithm to Find the Convex Hull
Java Program to Implement Direct Addressing Tables
Java Program to Implement AVL Tree
JavaScript Styles and classes
Java Program to Generate Random Numbers Using Multiply with Carry Method
Spring Boot - Tracing Micro Service Logs
An Example of Load Balancing with Zuul and Eureka
Upload and Display Excel Files with Spring MVC