简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
下面我们来看看需要装箱拆箱的类型有哪些:
这个过程是自动执行的,那么我们需要看看它的执行过程:
反编译 class 文件之后得到如下内容:
1 javap -c StringTest
Integer total = 99;
执行上面那句代码的时候,系统为我们执行了:
Integer total = Integer.valueOf(99);
int totalprim = total;
执行上面那句代码的时候,系统为我们执行了:
int totalprim = total.intValue();
我们现在就以 Integer 为例,来分析一下它的源码:
1、首先来看看 Integer.valueOf 函数
代码的后面,我们可以看到它们的执行结果是不一样的,为什么,在看看我们上面的说明。
1、i1和i2会进行自动装箱,执行了valueOf函数,它们的值在(-128,128]这个范围内,它们会拿到 SMALL_VALUES数组里面的同一个对象 SMALL_VALUES[228],它们引用到了同一个 Integer 对象,所以它们肯定是相等的。
2、i3 和 i4 也会进行自动装箱,执行了 valueOf 函数,它们的值大于 128,所以会执行 new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。
下面我们来看看另外一个例子:
看看上面的执行结果,跟 Integer 不一样,这样也不必奇怪,因为它们的 valueOf 实现不一样,结果肯定不一样,那为什么它们不统一一下呢?
这个很好理解,因为对于 Integer,在(-128,128]之间只有固定的 256 个值,所以为了避免多次创建对象,我们事先就创建好一个大小为 256 的 Integer 数组SMALL_VALUES,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。
但是对于 Double 类型来说,我们就不能这样做,因为它在这个范围内个数是无限的。 总结一句就是:在某个范围内的整型数值的个数是有限的,而浮点数却不是。
所以在 Double 里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样。
总结
1、需要知道什么时候会引发装箱和拆箱
2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
3、equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型(a)是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱
4、当两种不同类型用 == 比较时,包装器类的需要拆箱, 当同种类型用==比较时,会自动拆箱或者装箱