Autoboxing and unboxing is introduced in Java 1.5 to automatically change the primitive type into the wrapper class and vice verse. With this feature, we can use primitives(
float…) and wrapper classes(
Float…) in many places interchangeably.
The following table lists the primitive types and their corresponding wrapper classes, which are used by the Java compiler for autoboxing and unboxing:
|Primitive type||Wrapper class|
Autoboxing is the automatic conversion that the Java compiler makes to change primitive types to their corresponding object wrapper classes. Here is an example for autoboxing.
According to the Java Docs, 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.
Unboxing is the opposite process of autoboxing.
The Java compiler applies unboxing when an object of a wrapper class 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.
Autoboxing and unboxing lets developers write cleaner code, making it easier to read, however there are some caveats we need to understand before utilizing them in production code.
As shown in the example from Javarevisited, autoboxing could throw away object which gets created if autoboxing occurs in a loop. This could potentially slow down the system with frequent garbage collection.
Refer to Javarevisited for more details.
As discussed in Javarevisited, we need method overloading to distinguish
value(Integer) since autoboxing/unboxing will potentially introduce subtle bugs if only either method exists.
ArrayList.remove() is overloaded by
remove(Object), so that autoboxing/unboxing won’t occur to confuse us by mixing removing object by index and removing object itself (e.g. especially when
Integer is the object).
I would like to borrow the example again from Javarevisited. More details can be found on the original post.
Here is the output.
I would like to put the insightful explanation from the original post here.
In first example both argument of == operator is primitive int type so no autoboxing occurs and since
1==1it prints true.
While in second example during assignment to num1, autoboxing occurs which converts primitive 1 into
Integer(1)and when we compare
num1==num2unboxing occurs and
Integer(1)is converted back to 1 by calling Integer.intValue() method and since
1==1result is true.
In Third example which is a corner case in autoboxing, both Integer object are initialized automatically due to autoboxing and since
Integer.valueOf()method is used to convert int to Integer and it caches object ranges from -128 to 127, it returns same object both time. In short obj1 and obj2 are pointing to same object and when we compare two object with == operator it returns true without any autoboxing.
In last example object are explicitly initialized and compared using equality operator , this time == return false because both one and anotherOne reference variables are pointing to different object.