概念
简单说
装箱:装箱就是将基本数据类型转换为包装器类型,通过valueOf()函数实现装箱
拆箱:拆箱就是将包装器类型转换为基本数据类型,通过**×××Value()**函数实现拆箱
自动装箱:装箱中有一种非显示地装箱,即隐式装箱
自动拆箱:拆箱中有一种非显示地拆箱,即隐式拆箱
会发生装箱、拆箱的数据类型和包装类型
发生场景
可以先看原理,再回来自己分析场景
进行传参时,会发生自动装箱和拆箱
1 | public static void main(String[] args){ |
包装类和基本类型的大小比较
- 两个都为包装类型,比较的是地址(可能是一个对象,也有可能不是一个对象)
1 | Integer a = 1; |
- 两个都为基本数据类型,比较的是数值,并且数值不一样的会自动类型提升
1 | int e = 888; |
- 一个为包装类型,一个为基本数据类型,先进拆箱,转变为基本数据类型,再比较数值
1 | Integer a = 1; |
包装类型(和基本类型)的运算
1 | int i = 1; |
总结
当数据类型发生转变时,会发生装箱或者拆箱
当运算的时候,也会发生拆箱、再装箱
原理
不同数据类型的**×××Value()和valueOf()**的底层实现不同
所以,下面以Integer为例:
Integer装箱
1 | public class A { |
①对生成的class类进行反编译
可以看到调用了**Integer.valueOf()**方法,执行了装箱
②查看底层源码
解释:在Integer装箱时,如果值在-128到127之间,则会从内存中的IntegerCache.cache[]数组中找到现成的数据,以供使用(这个数组中的数据是Integer类的static静态代码块中初始过的,所以程序一运行时,这些数据就在内存中存在了);反之,如果数值在-128到127之外,则会重新new一个Integer类型的对象出来(也就出现了地址值不一样的现象)
Integer拆箱
1 | public class A { |
①对生成的class类进行反编译
可以看到,调用了**Integer.intValue()**方法,执行了拆箱
②查看底层源码
解释:可以看到,只返回了一个value,这个value其实是Integer的一个成员属性,value的值就是等于装箱的时候new Integer()时候的传入的int基本类型的值(数值),所以拆箱的时候,就是把包装类型的数据转换为基本类型数据
推广其他包装类
其他包装类和Integer类似,也都时通过是否new一个新的对象,来实现装箱、拆箱
装箱、拆箱目的
- 自动装箱、拆箱,有助于避免错误的发生:因为将包装类型的对象和基本数据类型进行转换时,自动装箱总是生成一个正确的对象,自动拆箱总是生成一个正确的值
- 有助于减少内存的浪费:例如Integer类的底层中有一个数组存放一定量的值
思考:装箱、拆箱的本质
装箱和拆箱的本质好像就是值类型和引用类型的互相转换。
装箱是值类型转换为引用类型;
拆箱就是引用类型转换为值类型。
tips:
java中除了int等基本数据类型是值类型外,其余所有的类型都称为引用类型(数组,类,接口,字符串)