Deep analysis of boxing and unboxing in Java

Keywords: Java

Automatic packing and unpacking is a common topic in Java. Today, let's take a look at some of the problems in packing and unpacking. This article first describes the basic things of packing and unpacking, and then look at the problems often encountered in the written test related to packing and unpacking.

The following is the catalogue outline of this article:


I. What is packing? What is boxbreaking?


2. How to realize packing and unpacking


III. Questions Relevant to Interview


If there are any shortcomings, please forgive and criticize and correct them.


I. What is packing? What is boxbreaking?


As mentioned in the previous article, Java provides the corresponding wrapper type for each basic data type. As for why it provides wrapper type for each basic data type, it is not explained here. Interested friends can refer to relevant information. Before Java SE5, if you want to generate an Integer object with a value of 10, you must do this:


Integer i = new Integer(10); 

Since Java SE5, the feature of automatic boxing has been provided. If you want to generate an Integer object with a value of 10, you just need to do this:


Integer i = 10; 

In this process, the corresponding Integer object is automatically created according to the numerical value, which is boxed.


So what is box-breaking? As the name implies, corresponding to packing, it automatically converts the packer type to the basic data type:


Integer i = 10;  //Boxing

int n = i;   //Unpacking


To put it simply, packing is  Automatically converts basic data types to wrapper types; unpacking is  Automatically converts the wrapper type to the basic data type.


The following table is the wrapper type corresponding to the basic data type:





































int(4 Byte) Integer
byte(1 Byte) Byte
short(2 Byte) Short
long(8 Byte) Long
float(4 Byte) Float
double(8 Byte) Double
char(2 Byte) Character
boolean(Undetermined) Boolean

Two.How to realize packing and unpacking


After understanding the basic concepts of packing in the previous section, this section looks at how packing and unpacking are realized.


We will take Interger For example, let's look at a piece of code:


public class Main {

    public static void main(String[] args) {

         

        Integer i = 10;

        int n = i;

    }

}


Decompile class After the document, the following contents are obtained:



As can be seen from the decompiled bytecode content, when boxed, the automatic call is Integer Of valueOf(int)Method. And when unpacking, the automatic call is Integer Of intValue Method.


Others are similar, such as Double,Character,A friend who doesn't believe in it can try it by hand.


So we can sum up the process of packing and unpacking in one sentence.


The packing process is done by calling the wrapper valueOf Method is implemented, and the unpacking process is done by calling the wrapper xxxValue The method is realized. ( xxx Represents the corresponding basic data type.


Three.Questions related to the interview


Although most people have a clear understanding of the concept of packing and unpacking, they may not be able to answer the questions about packing and unpacking in interviews and written examinations. Here are some common and boxed items/Interview questions related to unpacking.


1.What is the output 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 they will output false,Or some friends will say they will output true. But in fact the output is:




true
false


Why does this happen? Output results show that i1 and i2 Pointing to the same object, and i3 and i4 It points to different objects. At this point, just look at the source code to see exactly, the following code is Integer Of valueOf Specific implementation of the method:




public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}


Among them IntegerCache Class is implemented as:




private static class IntegerCache {
static final int high;
static final Integer cache[];

    <span class="hljs-keyword">static</span> {
        <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> low = -<span class="hljs-number">128</span>;

        <span class="hljs-comment">// high value may be configured by property</span>
        <span class="hljs-keyword">int</span> h = <span class="hljs-number">127</span>;
        <span class="hljs-keyword">if</span> (integerCacheHighPropValue != <span class="hljs-keyword">null</span>) {
            <span class="hljs-comment">// Use Long.decode here to avoid invoking methods that</span>
            <span class="hljs-comment">// require Integer's autoboxing cache to be initialized</span>
            <span class="hljs-keyword">int</span> i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, <span class="hljs-number">127</span>);
            <span class="hljs-comment">// Maximum array size is Integer.MAX_VALUE</span>
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = <span class="hljs-keyword">new</span> Integer[(high - low) + <span class="hljs-number">1</span>];
        <span class="hljs-keyword">int</span> j = low;
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>; k &lt; cache.length; k++)
            cache[k] = <span class="hljs-keyword">new</span> Integer(j++);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">IntegerCache</span><span class="hljs-params">()</span> </span>{}
}


From these two pieces of code, you can see that when you create an Integer object through the valueOf method, if the value is between [-128,127], you return a reference to an object that already exists in IntegerCache.cache; otherwise, you create a new Integer object.


In the above code, the values of i1 and i2 are 100, so the existing objects are 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 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);

    }

}


Some friends may think that the output of the above topic is the same, but in fact it is not. The actual output results are as follows:




false
false


As for why, readers can check it out. Double Class valueOf Implementation.


Just explain why. Double Class valueOf The method will be adopted with Integer Class valueOf Different implementations are used. Simple: The number of integer values in a range is limited, but floating-point numbers are not.


Be careful, Integer,Short,Byte,Character,Long Of these classes valueOf The implementation of the method is similar.


Double,Float Of valueOf The implementation of the method is similar.


3.What is the output 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 is:




true
true


As for why this is the result, again, see Boolean The source code of the class will also be clear at a glance. Below is Boolean Of valueOf Specific implementation of the method:




public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}


Among them TRUE and FALSE What is it? stay Boolean Two static member attributes are defined:




public static final Boolean TRUE = new Boolean(true);

<span class="hljs-comment">/** 
 * The &lt;code&gt;Boolean&lt;/code&gt; object corresponding to the primitive 
 * value &lt;code&gt;false&lt;/code&gt;. 
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Boolean FALSE = <span class="hljs-keyword">new</span> Boolean(<span class="hljs-keyword">false</span>);


At this point, you should understand why the output above is true.


4. Talk about the difference between Integer i = new Integer(xxx) and Integer i =xxx.


Of course, this topic belongs to a broader type. But the main points must be answered. Let me summarize the following two main differences:


1) The first mode will not trigger the process of automatic packing, while the second mode will trigger.


2) The difference in execution efficiency and resource occupation. The execution efficiency and resource usage of the second approach are generally better than the first (note that this is not absolute).


5. What is the output 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+b));

        System.out.println(g.equals(a+h));

    }

}


Instead of looking at the output, the reader thinks for himself what the output of this code is. It is important to note that when both operands of the "==" operator are references to the wrapper type, the comparison points to the same object, and if one of the operands is an expression (that is, contains arithmetic operations), the comparison is a numerical value (that is, triggers the automatic unboxing process). In addition, for wrapper types, the equals method does not perform type conversion. After understanding these two points, the above output results are clear at a glance:



true
false
true
true
true
false
true


There is no doubt about the first and second output results. Since a+b contains arithmetic operations, it triggers the automatic unboxing process (which calls the intValue method), so they compare whether the values are equal. For c.equals(a+b), the automatic unpacking process is triggered first, and then the automatic packing process is triggered. That is to say, a+b calls the intValue method respectively. After obtaining the value of the addition operation, the Integer.valueOf method is invoked, and then the equals comparison is made. The same is true for the latter, but note the results of the penultimate and final output (if the value is of type int, the packing procedure calls Integer.valueOf; if it is of type long, the packing procedure calls the Long.valueOf method).


If you have any questions about the above specific execution process, you can try to get the decompiled bytecode content for viewing.


 


 


 


Come from: http://blog.csdn.net/qq_35101189/article/details/53738371


 

Posted by idgeit on Fri, 12 Apr 2019 00:09:31 -0700