Autoboxing and Unboxing in Java – A Detailed Guide
Basics of SQL
12 Hrs. duration
12 Modules
2600+ Learners
Start Learning
When speaking of Java which is a strongly typed object-oriented programming language, it allows the person to work with both primitive types such as int, double, char, or such and also objects. But there is also a key difference between how the two types in Java work, objects and primitive types. For instance, primitive types are the direct holders of values while objects hold the pointers to the actual values stored in memory.
Java autoboxing and unboxing were introduced with the release of Java version 5. They enable the automatic conversion back and forth of the primitive types to corresponding object wrappers. In this article, we will take a thorough look into autoboxing and unboxing, how they work internally, their benefits & drawbacks, and how to implement them properly in Java with examples.
Why use Autoboxing and Unboxing in Java?
Java programmers are aware that primitive values, such as ints, cannot be added to collections. As collections can only contain object references, primitive values must be boxed into the relevant wrapper class (Integer in the case of int or String in the case of a string). The Integer that you entered is what you get when you remove the item from the collection; if you require an int, you must use the intValue function to unbox the Integer.
It messes up your coding and makes it difficult to box and unbox everything. The process is automated by autoboxing and unboxing, which removes the hassle and mess. But before we deep delve into learning about autoboxing and unboxing differences, it is necessary to understand what primitive types and wrapper classes are in Java.
Primitive Types and Wrapper Classes in Java
Before delving further into autoboxing and unboxing, it’s crucial to comprehend the connection between primitive types and the wrapper classes that correspond with them.
Primitive Types
Primitive types are simple and predefined types like integers, and booleans, used for basic data storage, and other use cases. There are 8 (eight) primitive types available in Java, each with a wrapper class that encapsulates its value.
Wrapper Classes
A wrapper class is a class that works by wrapping the objects of the primitive data types. It is because the generic classes essentially don’t support primitives and allow only functions with objects. Therefore, to operate with them, we must use wrapper objects from primitive values.
The Java Collection Framework only uses objects. The primitive values had to be manually transformed into matching wrapper classes before being placed in collections. A good method to use primitive data types as objects is using wrapper classes. There is a corresponding wrapper class for every primitive type.
In Java, there 8 (eight) wrapper classes for all primitive data types and these are:
Character -> char
Boolean -> boolean
String -> string
Integer -> int
Short -> short
Long -> long
Float -> float
Double -> double
In the wrapper classes, we have to manually specify the wrapper class to convert a primitive data type to an object or a corresponding wrapper class. But this task of manual conversion can be hectic. Therefore, we will use a concept known as boxing. Java provides two different types of boxing i.e., Autoboxing and Unboxing.
What is Autoboxing in Java?
Autoboxing is the Java compiler’s automatic conversion between the primitive types and their corresponding object wrapper classes. Developers can work more conveniently with both types when primitive data types are automatically converted to their wrapper classes by autoboxing.
Autoboxing means that the compiler automatically transforms a primitive value into an instance of the associated wrapper class when the primitive value is provided to a method or assigned to a variable that requires an object of the wrapper type. 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.
Syntax:
int myNum = 540;
Integer boxedMyNum = myNum;
In the above syntax, the primitive type int is automatically converted to its corresponding wrapper class Integer without any explicit conversion.
Internal Working of Autoboxing
The Java compiler handles autoboxing internally. The compiler adds a method call to transform the primitive type into an object when autoboxing takes place. Let’s see the internal workings of autoboxing with the help of an example:
Example:
int myNum = 540;
Integer boxedMyNum = myNum; // autoboxing
// What the compiler does behind the scenes:
Integer boxedMyNum = Integer.valueOf(myNum);
In the above example, the myNum variable contains a value of 540, and it is then autoboxed. The valueOf method is called to convert the primitive type into a wrapper object during autoboxing.
Example:
public class MainExample {
public static void main(String[] args) {
int primInt = 500;
// Autoboxing: converting the primitive int to a wrapper Integer object
Integer wrapInt = primInt;
System.out.println("Primitive int is: " + primInt);
System.out.println("Autoboxed Integer is: " + wrapInt);
}
}
Output:
Primitive int is: 500
Autoboxed Integer is: 500
In this example, the primitive int value 500 is automatically converted (autoboxed) to an Integer object when assigned to wrapInt.
Example:
import java.util.ArrayList;
import java.util.List;
public class MainExample {
public static void main(String[] args) {
// Autoboxing: int values are automatically converted to Integer objects
List<Integer> ls = new ArrayList<>();
ls.add(50); // Autoboxing from int to Integer
ls.add(60);
ls.add(70);
ls.add(80);
ls.add(90);
System.out.println("The given list is having Autoboxed Integers: " + ls);
}
}
Output:
The given list is having Autoboxed Integers: [50, 60, 70, 80, 90]
In this example, the primitive int values 50, 60, 70, 80, and 90 are automatically converted to Integer objects and stored in the ArrayList “ls”.
What is Unboxing in Java?
Unboxing refers to converting an object of a wrapper type (like an Integer) to its corresponding primitive (int) value. The opposite of autoboxing is unboxing. It entails automatically transforming a wrapper-type object into the matching primitive type. This usually occurs when a primitive type is anticipated in a scenario where a wrapper object is utilised. 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.
Syntax:
Integer myNum = new Integer(550);
int myUnboxedNum = myNum; // Unboxing
In the above syntax, the Integer object myNum is automatically unboxed to a primitive int when assigned to the myUnboxedNum variable.
Internal Working of Unboxing
The Java compiler handles unboxing internally. The compiler inserts a method call to retrieve the primitive value from the object during unboxing. Let’s see the internal working of unboxing with the help of an example:
Example:
Integer myNum = new Integer(550);
int myUnboxedNum = myNum; // Unboxing
// What the compiler does behind the scenes:
int myUnboxedNum = myNum.intValue();
In the above example, the myNum variable contains a value of 550, and it is then unboxed. The intValue method is called to convert the wrapper object back into a primitive type during unboxing.
Example:
public class MainExample { public static void main(String[] args) { Integer wrapInt = new Integer(40); // Unboxing: Integer object to primitive int int primInt = wrapInt; System.out.println(“Integer object is: ” + wrapInt); System.out.println(“Unboxed primitive int is: ” + primInt); } }
Output:
Integer object is: 40
Unboxed primitive int is: 40
In this example, the Integer object wrapInt is automatically converted (unboxed) to a primitive int when assigned to primInt.
Example:
import java.util.ArrayList;
import java.util.List;
public class MainExample {
public static void main(String[] args) {
Integer wrpInt1 = new Integer(50);
Integer wrpInt2 = new Integer(10);
// Unboxing: Integer objects to primitive int for arithmetic operation
int res = wrpInt1 / wrpInt2;
System.out.println("The result of Unboxed Integers: " + res);
}
}
Output:
The result of Unboxed Integers: 5
In this example, the Integer objects wrpInt1 and wrpInt2 are automatically unboxed to int values for the division operation, and the result is stored as a primitive int.
Autoboxing and Unboxing provide different benefits in Java that are beneficial for every user using Java for building scalable, efficient applications. Here are some benefits of autoboxing and unboxing:
Code Simplification: It is one of the most significant advantages because, with autoboxing and unboxing, the code is simplified. This makes the code cleaner and more readable. It means that developers do not need to convert explicitly between primitive types and their corresponding wrapper classes anymore.
Convenience: Letting you work with both primitive types and their wrapper classes without explicit conversions is what autoboxing and unboxing stand for in a convenient way.
Reduced Boilerplate: Before Java 5, developers had to manually wrap primitive types. This resulted in verbose code. With the help of autoboxing and unboxing, you can get rid of this boilerplate.
Collections: Autoboxing allows the use of primitive types in the Java collections framework. For example, ArrayLists and HashMaps, which usually require object types.
Seamless Interaction with Collections: Java collections work with objects, not primitive types. Autoboxing is the Java compiler’s automatic conversion between the primitive types and their corresponding object wrapper classes. For example, it allows primitives to be used directly in collections without manual conversions to wrapper types.
Common Pitfalls of Autoboxing and Unboxing
Although autoboxing and unboxing make programming simpler and provide many benefits, they may also result in performance problems and minute flaws. Let’s see a few typical pitfalls:
Null Pointer exception: Unboxing a null reference might result in a NullPointerException. Null because primitive types can not hold and if you try to unbox a wrapper object that is actually. For example:
Example:
Integer nullInteger = null;
int num = nullInteger; // it will throw a NullPointerException
Impact on Performance: Autoboxing/unboxing is an operation with performance overhead since each conversion involves incidental memory allocation for the object, which then needs to be garbage-collected. It results in repeated autoboxing/unboxing operations getting a significant performance overhead. Thus minimise the use of wrapper classes in performance-critical sections of your code. See the below example:
Example:
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
list.add(i); // Autoboxing of int to Integer
}
Boxing Inside loops: When autoboxing happens inside loops, it can result in decreased performance since it will create objects over and over again.
Equality check: Watch out when comparing primitive types with wrapper objects. For example, using the == operator between a primitive type and a wrapper object can cause unexpected results because of unboxing.
The n3 and n4 are true because Java caches small values that are between -128 and 127, so comparing Integer objects within this range may return true for the == operator, whereas larger values result in false.
Difference between Autoboxing and Unboxing
The key differences between autoboxing and unboxing are as follows:
Criteria
Autoboxing
Unboxing
Definition
Autoboxing refers to automatic conversion of a primitive type to its wrapper class.
Unboxing refers to automatic conversion of a wrapper class to its primitive type.
Direction of conversion
From a primitive type (e.g., int, double, boolean) to a wrapper object (e.g., Integer, Double, Boolean).
From a wrapper object (e.g., Integer, Double, Boolean) to a primitive type (e.g., int, double, boolean).
Null Pointer
There is no risk of null pointer exception, as primitive types cannot be null.
There is a risk of a null pointer exception if the object is null.
Trigger
Trigger occurs when an object is assigned as an argument, or when a primitive value is set to a variable of a wrapper type.
It happens when an action that requires a primitive is performed, or when a wrapper object is used in place of a primitive variable.
Memory overhead
It causes memory overhead by creating a new object in memory.
It uses the primitive value directly, saving the object from additional memory overhead.
Performance
Slower because of object formation than when utilising primitive types directly.
Faster to retrieve primitive values, but more risky if null is found.
Operator support
Autoboxed objects can take part in processes that are object-based (such as method parameters and collection storage).
Unboxed values are capable of taking part in bitwise and arithmetic operations, among other primitive-based activities.
Impact on code readability
Autoboxing eliminates the need for explicit primitive-to-object conversion, therefore reducing boilerplate code.
Unboxing eliminates the need for explicit object-to-primitive conversions, simplifying code.
Example
Integer i = 40;
int i= new Integer(40);
Best Practices for Using Autoboxing and Unboxing
While there are some common pitfalls for autoboxing and unboxing, applying some of the best practices in Java can improve your code readability and reduce verbosity. Here are the best practices:
Avoid Autoboxing in Code That Is Critical to Performance
For code with strict memory limitations or real-time applications, for example, where performance is a top concern, steer clear of autoboxing and utilise primitive types directly.
Use Null References With Care
Before unwrapping an object while working with wrapper classes, make sure it is not null. NullPointerException can be avoided with a null check.
Use equals()
The equals() method is always preferable to the == operator when comparing wrapper objects because the latter only verifies value equality, not reference equality.
Don’t Autobox in Repeats
Repeated autoboxing within loops may cause the system to perform worse. Use primitive types in loops if at all possible.
Conclusion
Autoboxing and unboxing represent powerful features in Java because they simplify the conversion between primitive types and their corresponding wrapper classes. By eliminating the need for explicit conversions, they make code more readable and reduce boilerplate. In this article, we have learned the difference between Autoboxing and Unboxing in Java, along with their benefits, internal workings, pitfalls, and drawbacks.
Autoboxing and unboxing, however, have certain possible drawbacks, such as performance overhead and the possibility of NullPointerException, just like any other feature. Writing dependable and effective Java code requires an understanding of frequent problems, performance implications, and the inner workings of autoboxing and unboxing.
Best practices will help Java developers take full advantage of autoboxing and unboxing while steering clear of pitfalls, which typically result from their misuse. The efficiency of primitive types is balanced with the flexibility of objects by autoboxing and unboxing— making Java both powerful and developer-friendly. They are, however, like all tools, to be used judiciously for high performance and reliability of the code.
FAQs
How does autoboxing differ from unboxing in Java?
Autoboxing in Java refers to the automatic wrapping of a primitive type that is occurring in a corresponding wrapper class object. The reversing action of this process is known as unboxing. For example, changing an int to an Integer is a process of auto boxing, whereas changing an Integer to an int is the process of unboxing.
How does the compiler perform autoboxing and unboxing?
The valueOf() method is a special function provided by the compiler to carry out the autoboxing of primitives into wrapper objects, and intValue() and doubleValue() methods are meant for unboxing.
Why are autoboxing and unboxing useful?
It improves code usability and reduces the amount of code the programmer has to write by enabling the compilation of resources of various data types in a single operation.
How does unboxing work in Java?
The internal working of unboxing in Java is simpler. When one executes an operation that uses a primitive type and provides a value as a wrapper object, Java will instead convert that wrapper object (which is an instance of a wrapper class). For example, when you write:
int primInt = wrapInt;
The Java compiler translates it into something like this behind the scenes:
int primInt = wrapInt.intValue();
Within the integer wrapper class, the .intValue() method is used in the class and this is used to obtain the integer value from the Integer wrapper class.
What are the benefits of Autoboxing?
There are various benefits of autoboxing like the readability, code is easy to read because there is no need to provide the relevant wrapper class when any of the primitives are being used in the code. That makes it possible to use the primitives in the collection and the object-based operations.
Hero Vired is a leading LearnTech company dedicated to offering cutting-edge programs in collaboration with top-tier global institutions. As part of the esteemed Hero Group, we are committed to revolutionizing the skill development landscape in India. Our programs, delivered by industry experts, are designed to empower professionals and students with the skills they need to thrive in today’s competitive job market.