1、什么是自动装箱与拆箱
//自动装箱
Integer integer = 100;
//自动拆箱
int i = integer;
装箱:自动将基本类型转化为包装类
拆箱:自动将包装类转化为基本类型
2、基本原理
(1)、自动装箱,valueOf()
Integer integer = 100 时系统自动执行了 Integer integer = Integer.valueOf(100);
Integer.valueOf 源码
static final int low = -128;
static final int high;
static final Integer cache[];
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
![](https://img.haomeiwen.com/i5182413/f9eebda6f07b315e.png)
首先判断i大小,是否在low (-128) 与high (默认127) 之间,不在就新创建一个Integer对象,否则返回cache数组。
这里注意:
a、在某个范围内的整型数值的个数是有限的,而浮点数却不是。所以Double Float不会有数组出现。
b、cache 是一个静态的Integer数组,也就是说如果在low与high之间,返回的都是一个integer对象。
c、装箱过程会创建相应的对象,会消耗内存,影响性能。
(2)、自动拆箱,intValue()
int i = integer 时系统自动执行了 int i = integer.intValue();
intValue 源码
public int intValue() {
return value;
}
3、相关问题
(1)、自动装箱 == 问题
a、Integer在 (-127,128] 有限个数
Integer integer1 = 100;
Integer integer2 = 100;
Integer integer3 = 200;
Integer integer4 = 200;
System.out.println(integer1 == integer2); //true
System.out.println(integer3 == integer4); //false
这里都会进行自动装箱,但是 integer1、integer2 因为在-127到128 范围内,所以返回了同一个Integer对象,所以他们是相等的
integer3、integer4也会进行自动封箱,但是因超出范围,都会返回 new Integer(200) ,所以不相等。
b、Double类型
Double aDouble1 = 100.0;
Double aDouble2 = 100.0;
Double aDouble3 = 100.0;
Double aDouble4 = 100.0;
System.out.println(aDouble1 == aDouble2); //false
System.out.println(aDouble3 == aDouble4); //false
这里和Integer不太一样,因为valueOf的实现不一样,对于Integer在某个范围内个数有限,所以为避免多次创建对象,java8会直接创建好一个大小为256的Integer数组,如果在这个范围内,直接返回这个对象。
但是Double,在这个范围内是无限的,所以只能每次都新创建一个对象。类似的还有Float。
c、Boolean
对于Boolean类型,只有两种情况,所以都是提前创建好的,这样也是为了避免创建过多对象。
![](https://img.haomeiwen.com/i5182413/78ece032ee99499a.png)
(2)、Integer.equals(int) 问题
Integer i1 = 10;
int i2 = 10;
System.out.println(i1 == i2); //true
System.out.println(i1.equals(i2)); //true
对于 == 操作,i1会进行自动拆箱。
对于 equals 操作,传入的是int,但源码参数是Object类型,所以会进行自动封箱,返回 true 是因为比较的是对象里的值,这里是重写了Object里面的 equals 方法,若不重写 equals 方法则比较的是引用对象的对象地址。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
(3)、不同类型数值 == 与 equals 问题
Integer num1 = 1;
int num2 = 1;
Long num3 = 2l;
System.out.println(num1 + num2); //2
System.out.println(num3 == (num1 + num2)); //true
System.out.println(num3.equals(num1 + num2)); //false
首先进行+ - * / == 运算会进行拆箱,进行基本数据类型之间运算、比较。
equals 返回 false 是因为在比较 equals 时会进行自动封箱,只有当类型相同、内容相同时才返回true。
(4)、不同类型不涉及基本类型比较 ==
Integer num1 = 100;
Ingeger num2 = 200;
Long num3 = 300l;
System.out.println(num3 == (num1 + num2)); //true
进行 == 时 num3 进行拆箱,num1 + num2 进行拆箱
(5)、基本类型测试
int num1 = 100;
int num2 = 200;
long mum3 = 300;
System.out.println(num3 == (num1 + num2)); //true
对 (4) 的解释,基本类型比较的是数值
所以,当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。
(6)、包装类可以初始化为null,在进行拆箱时会报空指针异常
Integer integer = null;
int i = integer;
所以有拆箱操作的时候要注意是否为null。
4、总结一下:
拆箱:包装类型 ----> 基本类型 ----> ==、运算
装箱:基本类型 ----> 包装类型 ----> equals
网友评论