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 object or 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.


» 下一篇: Java KeyStore 接口