In this article, we will look at such a function in Java as autoboxing / unpacking . Autoboxing and unboxing is a function of converting primitive types to object types and vice versa. The entire process is done automatically by the Java Runtime Environment (JRE). But you should be careful when implementing this function, because. It can affect the performance of your program.
Table 1: Primitive types and equivalent wrapper classes with comparison operators Autoboxing and unboxing can be used with comparison operators. The following code snippet illustrates how this works: Listing 3: Code example showing autoboxing and unboxing with a comparison operator
Introduction
In versions prior to JDK 1.5, it was not easy to convert primitive data types such asint
, char
, float
, double
to their Integer, Character, Float, Double wrapper classes. Starting with JDK 5, this feature, converting primitive types to equivalent objects, is implemented automatically. This property is known as Autoboxing . The reverse process, respectively - Unboxing (Unboxing) i.e. the process of converting objects to their corresponding primitive types. Sample code for autopacking and unpacking is shown below: Autopacking
Integer integer = 9;
Unboxing
int in = 0;
in = new Integer(9);
When is autopacking and unpacking used? Autoboxing is applied by the Java compiler under the following conditions:
- When a value of a primitive type is passed to a method as a method parameter that expects an object of the corresponding wrapper class.
- When a value of a primitive type is assigned to a variable, the corresponding wrapper class.
public int sumEvenNumbers(List<Integer> intList ) {
int sum = 0;
for (Integer i: intList )
if ( i % 2 == 0 )
sum += i;
return sum;
}
Prior to jdk 1.5, the above code would cause a compile-time error because the remainder operator % and the unary plus += could not be applied to the wrapper class. But in jdk 1.5 and above, this code compiles without error, converting Integer to int
. Unpacking is applied by the Java compiler under the following conditions:
- When an object is passed as a parameter to a method that expects the corresponding primitive type.
- When an object is assigned to a variable of the corresponding primitive type.
import java.util.ArrayList;
import java.util.List;
public class UnboxingCheck {
public static void main(String[] args) {
Integer in = new Integer(-8);
// 1. Распаковка через вызов метода
int absVal = absoluteValue(in);
System.out.println("absolute value of " + in + " = " + absVal);
List<Double> doubleList = new ArrayList<Double>();
// Автоупаковка через вызов метода
doubleList.add(3.1416);
// 2. Распаковка через присвоение
double phi = doubleList.get(0);
System.out.println("phi = " + phi);
}
public static int absoluteValue(int i) {
return (i < 0) ? -i : i;
}
}
Autoboxing and unboxing allows a developer to write code that is easy to read and understand. The following table shows the primitive data types and their corresponding wrapper objects.
Primitive types | Shell classes |
---|---|
boolean | Boolean |
byte | bytes |
char | character |
float | float |
int | Integer |
long | Long |
short | short |
public class BoxedComparator {
public static void main(String[] args) {
Integer in = new Integer(25);
if (in < 35)
System.out.println("Value of int = " + in);
}
}
Autoboxing and Unboxing on Method Overloading Autoboxing and unboxing is performed when a method is overloaded based on the following rules:
- Extension "beats" packaging in a situation where there is a choice between extension and packaging, extension is preferable.
public class WideBoxed {
public class WideBoxed {
static void methodWide(int i) {
System.out.println("int");
}
static void methodWide( Integer i ) {
System.out.println("Integer");
}
public static void main(String[] args) {
short shVal = 25;
methodWide(shVal);
}
}
}
Program output - typeint
- Expansion beats variadic arguments In a situation where there is a choice between expansion and varargument, expansion is preferable.
public class WideVarArgs {
static void methodWideVar(int i1, int i2) {
System.out.println("int int");
}
static void methodWideVar(Integer... i) {
System.out.println("Integers");
}
public static void main( String[] args) {
short shVal1 = 25;
short shVal2 = 35;
methodWideVar( shVal1, shVal2);
}
}
- Boxing beats variadic arguments In a situation where the choice is between boxing and variadic arguments, boxing is preferable.
public class BoxVarargs {
static void methodBoxVar(Integer in) {
System.out.println("Integer");
}
static void methodBoxVar(Integer... i) {
System.out.println("Integers");
}
public static void main(String[] args) {
int intVal1 = 25;
methodBoxVar(intVal1);
}
}
You should keep the following things in mind when using AutoPack: As we know, every good feature has a flaw. Autopacking is no exception in this regard. Some important notes that a developer should keep in mind when using this feature:
- Comparing objects with the '
==
' operator can be confusing because it can be applied to primitive types and objects. When this operator is applied to objects, it actually compares object references, not the objects themselves.
public class Comparator {
public static void main(String[] args) {
Integer istInt = new Integer(1);
Integer secondInt = new Integer(1);
if (istInt == secondInt) {
System.out.println("both one are equal");
} else {
System.out.println("Both one are not equal");
}
}
}
- Mixing objects and primitive types with the equality and relation operator. If we compare a primitive type with an object, then the object is unpacked, which can throw
NullPointerException
if the objectnull
. - Object caching. The method
valueOf()
creates a container of primitive objects that it caches. Since values are cached in the range -128 to 127 inclusive, these cached objects can behave differently. - Performance degradation. Autoboxing or unboxing degrades application performance because it creates an unwanted object that causes the garbage collector to run more frequently.
public int sumEvenNumbers(List intList) {
int sum = 0;
for (Integer i : intList) {
if (i % 2 == 0) {
sum += i;
}
}
return sum;
}
In this section of code, sum +=i
will be expanded to sum = sum + i
. Starting with the ' +
' operator, the JVM starts unboxing because the ' +
' operator cannot be applied to an Integer object. And then the result is autopacked back. Prior to JDK 1.5, datatypes int
and Integer types were different. In the case of method overloading, these two types were used without problems. With the advent of automatic packaging / unpacking, this has become more difficult. An example of this is the overloaded method remove()
in ArrayList
. The class ArrayList
has two delete methods - remove(index)
and remove(object)
. In this case, method overloading will not occur and the corresponding method will be called with the appropriate parameters.
Conclusion
Autoboxing is a mechanism for implicitly converting primitive data types into appropriate wrapper classes (objects). The compiler uses the methodvalueOf()
to convert the primitive types to objects, and the methods IntValue()
, doubleValue()
etc. to get the primitive types of the object. Autoboxing converts Boolean boolean
to Boolean, byte
to Byte, char
to Character, float
to Float, int
to Integer, long
to Long, short
to Short. Unpacking occurs in the opposite direction. Original article
GO TO FULL VERSION