前言
在JAVA中,拆箱和装箱操作是发生在基本数据类型和其包装类之间的一种操作。
JAVA中的八种基本类型有:byte short int long float double boolean char
每一种基本数据类型在java中对应的会有一个包装类,其目的是为了丰富其功能。对应关系如下图所示:
一、名词解释
装箱:将基本数据类型转为其包装类就为装箱操作
拆箱:将其包装类转为基本数据类型就为拆箱操作
二、原理:(以int和包装类Integer讲解,其他的类型同理)
Integer a = 100; //100为基本类型,将100赋值给a就会发生自动装箱的操作
int b = a; //此时a为包装类型,将a赋值给b 就会自动发生拆箱操作。
实际发生的操作:
在装箱时会自动调用 Integer 的 valueOf()方法,在拆箱时会自动调用intValue()方法,源码如下
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
/**
* Returns the value of this {@code Integer} as an
* {@code int}.
*/
public int intValue() {
return value;
}
注意:Java 基本类型的包装类的大部分都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean;前面 4 种包装类默认创建了数值[-128,127] 的相应类型的缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean 直接返回True Or False。如果超出对应范围仍然会去创建新的对象。两种浮点数类型的包装类 Float,Double 并没有实现常量池技术
三、实际问题
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);//输出 false
解释:
Integer i1 = 40; Java 在编译的时候执行的代码是Integer.valueOf(40),从而使用的是常量池中的数据
Integer i2 = new Integer(40); 创建的新的对象
所以两个对象不相等
Integer i1 = 40;
Integer i2 = 40;
System.out.println("i1=i2 " + (i1 == i2)); //true
解释:
Integer i1 = 40;
Integer i2 = 40;会发生装箱操作,实际执行的代码是 Integer.valueOf(40),而40是在缓存范围内的,
所以i1 i2都是用的缓存池中的同一数据,地址相同,所以两个对象 == 为true
Integer i1 = 333;
Integer i2 = 333;
System.out.println("i1=i2 " + (i1 == i2)); //false
解释:
Integer i1 = 40;
Integer i2 = 40;会发生装箱操作,实际执行的代码是 Integer.valueOf(40),而333不在缓存范围内,
所以会创建新的Integer对象,地址不同,所以两个对象 == 为false
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //输出true
解释:
先计算i2 + i3 ,i2 i3 发生自动拆箱,然后进行相加得到一个int值
然后判断相等时,i1又发生自动拆箱,最后还是两个int数值比较相等
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
System.out.println("i4=i5 " + (i4 == i5));//输出false
解释:
两个对象 == 比较,比较的是地址,所以不相等