The automatic packing and unboxing issue is a common issue in Java. Today we will take a look at some of the issues in packing and unboxing. This article first talks about the most basic things about packing and unboxing, and then take a look at the problems related to packing and unboxing that are often encountered in the written test below.
1. What is packing? What is unboxing?
In the previous article, Java provides corresponding wrapper types for each basic data type. As for why the wrapper types are provided for each basic data type, it will not be explained here. Interested friends can consult the relevant information. Before Java SE5, if you want to generate an Integer object with a value of 10, you must do this:
The code copy is as follows:
Integer i = new Integer(10);
Since Java SE5, the automatic boxing feature is provided. If you want to generate an Integer object with a value of 10, you just need to do this:
The code copy is as follows:
Integer i = 10;
In this process, the corresponding Integer object will be automatically created based on the numerical value, which is packing.
So what is unboxing? As the name implies, it corresponds to packing, which automatically converts the wrapper type to the basic data type:
The code copy is as follows:
Integer i = 10; //packing
int n = i; //Unbox
To put it simply, packing means automatically converting the basic data type to the wrapper type; unboxing means automatically converting the wrapper type to the basic data type.
The following table is the wrapper type corresponding to the basic data type:
2. How is packing and unboxing implemented?
After understanding the basic concepts of packing in the previous section, this section will understand how packing and unboxing are implemented.
Let’s take the Interger class as an example, and see a piece of code below:
public class Main {public static void main(String[] args) {Integer i = 10;int n = i;}}After decompiling the class file, you will get the following content:
From the bytecode content obtained by decompiling, it can be seen that the valueOf(int) method of Integer is automatically called when packing. When unboxing, the intValue method of Integer is automatically called.
Others are similar, such as Double or Character. Friends who don’t believe in it can try it manually by themselves.
Therefore, the implementation process of packing and unboxing can be summarized in one sentence:
The boxing process is implemented by calling the valueOf method of the wrapper, while the unboxing process is implemented by calling the xxxValue method of the wrapper. (xxx represents the corresponding basic data type).
3. Related questions during the interview
Although most people are clear about the concepts of packing and unboxing, they may not be able to answer questions about packing and unboxing during interviews and written tests. Below are some common interview questions related to packing/unboxing.
1. What is the output result of the following code?
public class Main {public static void main(String[] args) {Integer i1 = 100;Integer i2 = 100;Integer i3 = 200;Integer i4 = 200;System.out.println(i1==i2);System.out.println(i3==i4);}} Maybe some friends will say that they will output false, or some friends will say that they will output true. But in fact the output is:
true
false
Why does such a result occur? The output results show that i1 and i2 point to the same object, while i3 and i4 point to different objects. At this point, you only need to look at the source code to know the truth. The following code is the specific implementation of Integer's valueOf method:
public static Integer valueOf(int i) {if(i >= -128 && i <= IntegerCache.high)return IntegerCache.cache[i + 128];elsereturn new Integer(i);} The implementation of the IntegerCache class is:
private static class IntegerCache {static final int high;static final Integer cache[];static {final int low = -128;// high value may be configured by propertyint h = 127;if (integerCacheHighPropValue != null) {// Use Long.decode here to avoid invoking methods that// require Integer's autoboxing cache to be initializedint i = Long.decode(integerCacheHighPropValue).intValue();i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - -low);}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);}private IntegerCache() {}} From these two pieces of code, when creating an Integer object through the valueOf method, if the value is between [-128, 127], a reference to the object that already exists in IntegerCache.cache is returned; otherwise, a new Integer object is created.
In the above code, the values of i1 and i2 are 100, so the existing objects will be taken directly from the cache, so i1 and i2 point to the same object, while i3 and i4 point to different objects respectively.
2. What is the output result of the following code?
public class Main {public static void main(String[] args) {Double i1 = 100.0;Double i2 = 100.0;Double i3 = 200.0;Double i4 = 200.0;System.out.println(i1==i2);System.out.println(i3==i4);}} Maybe some friends will think that the output result is the same as the above question, but in fact it is not. The actual output is:
false
false
As for the specific reason, readers can check the implementation of the valueOf of the Double class.
Here I will only explain why the valueOf method of the Double class adopts a different implementation than the valueOf method of the Integer class. It's very simple: the number of integer values in a certain range is finite, but floating point numbers are not.
Note that the implementation of valueOf methods of Integer, Short, Byte, Character, and Long are similar.
The implementation of the valueOf method of Double and Float is similar.
3. What is the output result of the following code:
public class Main {public static void main(String[] args) {Boolean i1 = false;Boolean i2 = false;Boolean i3 = true;Boolean i4 = true;System.out.println(i1==i2);System.out.println(i3==i4);}} The output result is:
true
true
As for why this result is, you will also be clear at a glance after reading the source code of the Boolean class. The following is the specific implementation of Boolean's valueOf method:
public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE);} And what are TRUE and FALSE? 2 static member properties are defined in Boolean:
public static final Boolean TRUE = new Boolean(true);/** * The <code>Boolean</code> object corresponding to the primitive * value <code>false</code>. */public static final Boolean FALSE = new Boolean(false);
At this point, everyone should understand why the above output is true.
4. Talk about the difference between Integer i = new Integer(xxx) and Integer i =xxx;
Of course, this topic belongs to a relatively broad type. But the key points must be answered. Let me summarize the following two differences:
1) The first method will not trigger the automatic boxing process; while the second method will trigger;
2) The difference in execution efficiency and resource utilization. The second method of execution efficiency and resource usage are better than the first in general (note that this is not absolute).
5. What is the output result of the following program?
public class Main {public static void main(String[] args) {Integer a = 1;Integer b = 2;Integer c = 3;Integer d = 3;Integer e = 321;Integer f = 321;Long g = 3L;Long h = 2L;System.out.println(c==d);System.out.println(e==f);System.out.println(c==(a+b));System.out.println(c.equals(a+b));System.out.println(g==(a+b));System.out.println(g.equals(a+h));}} Don’t look at the output results first, readers will think about the output results of this code for themselves. What should be noted here is that when the two operands of the "==" operator are references to the wrapper type, it compares whether the pointer is the same object, and if one of the operands is an expression (that is, contains arithmetic operations), it compares the numerical values (that will trigger the automatic unboxing process). In addition, for wrapper types, the equals method does not perform type conversion. After understanding these 2 points, the above output results will be clear at a glance:
true
false
true
true
true
false
true
There is no doubt about the first and second output results. In the third sentence, since a+b contains arithmetic operations, it triggers the automatic unboxing process (the intValue method will be called), so they compare whether the values are equal. For c.equals(a+b), the automatic unboxing process will be triggered first, and then the automatic packing process will be triggered. That is to say, a+b, each will call the intValue method, and after obtaining the value after the addition operation, the Integer.valueOf method will be called, and then the equals comparison will be performed. The same is true for the following, but pay attention to the results of the second to last and last output (if the value is of type int, the boxing process calls Integer.valueOf; if it is of type long, the boxing method calls Long.valueOf).
The above is a deep understanding of packing and unboxing in Java introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!