Home  >  Article  >  Java  >  In-depth understanding of boxing and unboxing in Java

In-depth understanding of boxing and unboxing in Java

高洛峰
高洛峰Original
2017-01-24 14:03:451424browse

The issue of automatic boxing and unboxing is a commonplace issue in Java. Today we will take a look at some issues in boxing and unboxing. This article first talks about the most basic things about packing and unboxing, and then looks at the questions related to packing and unboxing that are often encountered in written interviews.

1. What is boxing? What is unboxing?

As mentioned in the previous article, Java provides corresponding wrapper types for each basic data type. As for why it provides wrapper types for each basic data type, we will not discuss it here. Explanation, interested friends can check relevant information. Before Java SE5, if you want to generate an Integer object with a value of 10, you must proceed like this:

Integer i = new Integer(10);

Starting from Java SE5, the autoboxing feature has been provided. If you want to generate an Integer object with a value of 10, Integer objects, all you need is this:

Integer i = 10;

In this process, the corresponding Integer objects will be automatically created based on the values, which is boxing.

So what is unboxing? As the name suggests, corresponding to boxing, it automatically converts the wrapper type into the basic data type:

Integer i = 10; //装箱
int n = i; //拆箱

To put it simply, boxing means automatically converting the basic data type into the wrapper type; unboxing means automatically converting the packaging type converter type to basic data type.

The following table shows the wrapper types corresponding to basic data types:

In-depth understanding of boxing and unboxing in Java

2. How boxing and unboxing are implemented

After understanding the basic concepts of boxing in the previous section, let’s learn how boxing and unboxing are implemented in this section.

Let’s take the Interger class as an example. Let’s look at a piece of code:

public class Main {
public static void main(String[] args) {
Integer i = 10;
int n = i;
}
}

After decompiling the class file, we get the following content:

In-depth understanding of boxing and unboxing in Java

It can be seen from the bytecode content obtained by decompilation that the valueOf(int) method of Integer is automatically called during boxing. What is automatically called during unboxing is the intValue method of Integer.

Others are similar, such as Double and Character. Friends who don’t believe it can try it manually.

So the implementation process of boxing and unboxing can be summarized in one sentence:

The boxing process is implemented by calling the valueOf method of the wrapper, and the unboxing process The process is implemented by calling the xxxValue method of the wrapper. (xxx represents the corresponding basic data type).

3. Questions related to the interview

Although most people are clear about the concepts of packing and unpacking, they encountered problems related to packing in interviews and written tests. The question of boxing and unboxing may not be answered. Here are some common interview questions related to packing/unboxing.

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 that it will output false, or some friends will say that it will output true. But in fact the output result is:

true
false

Why does this result appear? The output shows 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 the valueOf method of Integer:

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

And 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 property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer&#39;s autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = 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() {}
}

It can be seen from these two pieces of code that when creating an Integer object through the valueOf method, if the value is between [-128,127], then Returns a reference to an object that already exists in IntegerCache.cache; otherwise creates a new Integer object.

In the above code, the values ​​​​of i1 and i2 are 100, so the existing objects will be fetched directly from the cache, so i1 and i2 point to the same object, while i3 and i4 are 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 result of the above question is the same, but in fact it is not. The actual output result is:

false
false

As for the specific reason, readers can check the implementation of valueOf of the Double class.

In-depth understanding of boxing and unboxing in Java

Here I will just explain why the valueOf method of the Double class uses a different implementation than the valueOf method of the Integer class. It's simple: the number of integer values ​​within a certain range is finite, but floating point numbers are not.

Note that the implementation of the valueOf method of Integer, Short, Byte, Character, and Long classes 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

至于为什么是这个结果,同样地,看了Boolean类的源码也会一目了然。下面是Boolean的valueOf方法的具体实现:

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

   

而其中的 TRUE 和FALSE又是什么呢?在Boolean中定义了2个静态成员属性:

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);

   

至此,大家应该明白了为何上面输出的结果都是true了。

4.谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:

1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。

5.下面程序的输出结果是什么?

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));
}
}

   

先别看输出结果,读者自己想一下这段代码的输出结果是什么。这里面需要注意的是:当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。明白了这2点之后,上面的输出结果便一目了然:

true
false
true
true
true
false
true

第一个和第二个输出结果没有什么疑问。第三句由于 a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。

以上所述是小编给大家介绍的In-depth understanding of boxing and unboxing in Java,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网站的支持!

更多In-depth understanding of boxing and unboxing in Java相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn