The automatic boxing and unpacking is introduced from Java 1.5 to automatically convert the original type value to the corresponding object. The automatic boxing and unpacking mechanism allows us to use primitive types or object types more simply and directly in the case of Java variable assignment or method invocation.
If you had programmed under Java1.5, you wouldn't be unfamiliar with this, you can't put the original type value directly into the collection (collections) because the collection only receives objects. Typically, in this case, you would convert the values of these primitive types into objects and then put the transformed objects into the collection. Using these classes, such as Integer,double,boolean, we can convert raw type values into corresponding objects, but some degree may make the code less concise and refined. To make the code concise, Java 1.5 introduces a boxing and unboxing mechanism with automatic conversion of the original type and object type. However, automatic boxing and unpacking is not perfect, there are some precautions to use, and if you do not understand the automatic boxing and unpacking, it may cause imperceptible bugs.
This article describes what is automatic boxing and unpacking, when automatic boxing and unpacking occurs, and what to note.
What is auto-boxing and unpacking
Automatic boxing is that Java automatically converts the original type values into corresponding objects, such as converting an int variable to an integer object, a process called boxing, which translates an integer object into an int type value, which is called unpacking. Because the boxes and unboxing here are automatically non-human for conversion, it is called as automatic packing and unpacking. The wrapper class for the original type byte,short,char,int,long,float,double and Boolean is Byte,short,character,integer,long,float,double,boolean.
Automatic packing and unpacking essentials
- When the compiler calls valueof to convert the original type value to an object while auto-boxing, the compiler converts the object to the original type value by calling methods such as Intvalue (), Doublevalue (), and so on when the box is automatically disassembled.
- Auto Boxing is the conversion of a Boolean value to a Boolean object, a byte value to a Byte object, a char to a character object, a float value to a float object, an int to a integer,long converted to a long, Short is converted to short, and the automatic unpacking is the opposite operation.
When automatic boxing and unpacking occurs
Automatic boxing and unpacking is common in Java, for example, we have a method that accepts parameters of an object type, and if we pass a primitive type value, then Java automatically translates the original type value into its corresponding object. One of the most classic scenarios is when we add raw type data to a container such as ArrayList or create a parameterized class, such as the following threadlocal.
123456789 |
ArrayList<Integer> intList =
new ArrayList<Integer>();
intList.add(
1
);
//autoboxing - primitive to object
intList.add(
2
);
//autoboxing
ThreadLocal<Integer> intLocal =
new ThreadLocal<Integer>();
intLocal.set(
4
);
//autoboxing
int number = intList.get(
0
);
// unboxing
int local = intLocal.get();
// unboxing in Java
|
Examples Show
The above section introduces automatic boxing and unpacking and when they occur, we know that automatic boxing occurs mainly in two cases, one is assignment, the other is when the method is called. For a better understanding of both cases, we give an example.
When you assign a value
This is one of the most common cases where we need to manually convert before Java 1.5, and now all conversions are done by the compiler.
1234567 |
//before autoboxing Integer iObject = Integer.valueOf( 3 ); Int iPrimitive = iObject.intValue() //after java5 Integer iObject = 3 ; //autobxing - primitive to wrapper conversion int iPrimitive = iObject; //unboxing - object to primitive conversion |
When the method is invoked
This is another common case where we can pass in the original data value or object when we call the method, and the same compiler will help us with the conversion.
12345678 |
public static Integer show(Integer iParam){
System.out.println(
"autoboxing example - method invocation i: " + iParam);
return iParam;
}
//autoboxing and unboxing in method invocation
show(
3
);
//autoboxing
int result = show(
3
);
//unboxing because return type of method is Integer
|
The Show method takes an integer object as an argument, and when called show(3)
, converts the int value to the corresponding integer object, which is called auto-boxing, and the Show method returns an integer object with int result = show(3);
the result int type, So this happens when the auto-unpacking operation converts the returned integer object of the Show method to an int value.
The drawbacks of automatic boxing
Automatic boxing There is a problem with automatic boxing in a loop, as the following example creates extra objects that affect the performance of the program.
1234 |
Integer sum = 0 ; for ( int i= 1000 ; i< 5000 ; i++){ sum+=i; } |
The above code sum+=i
can be considered sum = sum + i
, but +
this operator does not apply to the integer object, first sum for the automatic unpacking operation, the numerical addition operation, and finally an automatic boxing operation converted to an integer object. The internal changes are as follows
12 |
sum = sum.intValue() + i; Integer sum = new Integer(result); |
Since the sum we declare here is of type integer, nearly 4,000 useless integer objects are created in the above loop, which in this large loop degrades the performance of the program and increases the amount of garbage collected. So when we're programming, we need to be aware of this and correctly declare variable types to avoid performance problems caused by automatic boxing.
Heavy and automatic boxing
When the overload is automatically boxed, the situation can be somewhat more complicated and may cause some confusion. Before 1.5, value (int) and value (Integer) are completely different methods, and developers will not be confused by which method to call in int or Integer, but because of the introduction of automatic boxing and unpacking, handling overloaded methods is a little more complicated. A typical example is the ArrayList remove method, which has remove(index)
and remove(Object)
two overloads, we may have a little bit of confusion, in fact, this confusion can be verified and solved, through the following example we can see that when this happens, the automatic boxing operation will not occur.
1234567891011121314151617181920 |
public void test(
int num){
System.out.println(
"method with primitive argument"
);
}
public void test(Integer num){
System.out.println(
"method with wrapper argument"
);
} //calling overloaded method
AutoboxingTest autoTest =
new AutoboxingTest();
int value =
3
;
autoTest.test(value);
//no autoboxing
Integer iValue = value;
autoTest.test(iValue);
//no autoboxing
Output:
method with primitive argument
method with wrapper argument
|
Things to keep in mind
Automatic boxing and unpacking can make the code concise, but there are some problems and extreme situations, the following points need us to pay more attention to.
Object Equality Comparison
This is a more error-prone place, "= =" can be used for the original value for comparison, can also be used to compare objects, when used in comparison between objects and objects, the comparison is not the value represented by the object, but to check whether two objects are the same object, the comparison process does not automatically boxing occurs. You should not use "= =" for object value comparisons, but instead use the Equals method of the object. Look at an example that can illustrate the problem.
1234567891011121314151617181920212223242526272829303132333435 |
public class AutoboxingTest {
public static void main(String args[]) {
// Example 1: == comparison pure primitive – no autoboxing
int i1 =
1
;
int i2 =
1
;
System.out.println(
"i1==i2 : " + (i1 == i2));
// true
// Example 2: equality operator mixing object and primitive
Integer num1 =
1
;
// autoboxing
int num2 =
1
;
System.out.println(
"num1 == num2 : " + (num1 == num2));
// true
// Example 3: special case - arises due to autoboxing in Java
Integer obj1 =
1
;
// autoboxing will call Integer.valueOf()
Integer obj2 =
1
;
// same call to Integer.valueOf() will return same
// cached Object
System.out.println(
"obj1 == obj2 : " + (obj1 == obj2));
// true
// Example 4: equality operator - pure object comparison
Integer one =
new Integer(
1
);
// no autoboxing
Integer anotherOne =
new Integer(
1
);
System.out.println(
"one == anotherOne : " + (one == anotherOne));
// false
}
}
Output:
i1==i2 :
true
num1 == num2 :
true
obj1 == obj2 :
true
one == anotherOne :
false
|
It is noteworthy that the third small example, this is an extreme situation. The OBJ1 and Obj2 initialization both occur with automatic boxing operations. But in memory-saving considerations, the JVM caches an integer object of 128 to 127. Because Obj1 and obj2 are actually the same object. Therefore, use the "= =" comparison to return true.
Easily confusing objects and raw data values
Another problem that needs to be avoided is the chaotic use of objects and raw data values, a concrete example of when we compare an object with an original data value, if the object is not initialized or null, Obj.xxxvalue in the automatic unpacking process will throw nullpointerexception, as in the following code
123456 |
private static Integer count; //NullPointerException on unboxing if ( count <= 0 ){ System.out.println( "Count is not started yet" ); } |
Cached objects
This problem is the extreme situation we mentioned above, in Java, the 128 to 127 of the integer object is cached, when creating a new integer object, if it conforms to this range, and there is already existing objects of the same value, then return this object, Otherwise, a new integer object is created.
Another example of saving memory in Java is the string constant pool, which interested students can look at.
Generating unwanted objects increases GC pressure
Because auto-boxing implicitly creates objects, as mentioned earlier, if you create useless intermediate objects in a loop body, you increase the GC pressure and slow down the performance of the program. So be sure to pay attention to the code when writing loops and avoid introducing unnecessary auto-boxing operations.
To learn about garbage collection and memory optimization, you can view the Google io:android memory management keynote transcript in this article
In general, the automatic packing and unpacking is really a great convenience for the developers, but in the use of it also need to pay extra attention to avoid causing the issue mentioned in the article.
Full understanding of Java Automatic Boxing and unpacking (GO)