Java自动装箱与自动拆箱
- Java自动装箱与自动拆箱的实现
- 何时会触发自动装箱与拆箱
- 常见题目
基本数据Java类型: 对应包装器类:
- int (4byte) Integer
- byte (1byte) Byte
- short (2byte) Short
- long (8byte) Long
- float (4byte) Float
- double (8byte) Double
- char (2byte) Character
- boolean (未定) Boolean
Integer i = 10; // 装箱 -- Integer.valueOf(10)
int n = i; // 拆箱 -- i.intValue()
装箱的时候自动调用的是Integer的valueOf(int)方法
拆箱的时候自动调用的是Integer的intValue方法
扩展
范例一:
Integer integer400 = 400;
int int400 = 400;
System.out.println(integer400 == int400);
== 运算 -> integer400 拆箱,结果为true
范例二:
Integer integer100=100;
int int100=100;
System.out.println(integer100.equals(int100));
方法中参数类型 -> 根据方法参数列表的类型 自动选择 装箱or拆箱,结果为int装箱,true
范例三:
Integer integer100 = 100;
int int100 = 100;
Long long200 = 200l;
System.out.println(integer100 + int100);
System.out.println(long200 == (integer100 + int100));
System.out.println(long200.equals(integer100 + int100));
+、-、*、/ 运算,自动拆箱
System.out.println(integer100 + int100); +号两边自动拆箱,相加,结果自动装箱,调用toString()
long200 == (integer100 + int100); +号两边自动拆箱,获得结果后 long200 拆箱,比较
long200.equals(integer100 + int100) +号两边自动拆箱,获得结果后自动装箱(Integer),Inteter类型和Long类型进行equals比较,结果为false
(两个 int 类型相加 ,自动装箱类型为Integer)
范例四:
Integer a = 1;
Integer b = 2;
Long g = 3L;
Long h = 2L;
System.out.println(g.equals(a+h));
g.equals(a+h); a+h 自动拆箱,a为int + h为long,结果为long,自动装箱为Long类型,结果为true
范例五:
Integer integer100 = null;
int int100 = integer100;
编译期不会报错
运行时:NullPointerException
问题:int int100 = integer100;
integer100 自动拆箱时,null.intValue()
范例六:
Integer i1=100;
Integer i2=100;
Integer i3=300;
Integer i4=300;
i1 == i2; // true
i3 == i4; // false
i1、i2、i3、i4 均为Integer类型
i1与i2这两个Integer类型的引用指向了同一个对象,而i3与i4指向了不同的对象
装箱时调用的是 Integer.valueOf(100)
// valueOf 的源码
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
当i>=-128且i<=IntegerCache.high时,直接返回IntegerCache.cache[i + 128]
IntegerCache为Integer的内部静态类
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'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() {}
}
IntegerCache有静态成员变量cache,为一个拥有256个元素的数组。
在IntegerCache中也对cache进行了初始化,即第i个元素是值为i-128的Integer对象。
而-128至127是最常用的Integer对象,这样的做法也在很大程度上提高了性能。
也正因为如此,“Integeri1=100;Integer i2=100;”,i1与i2得到是相同的对象。
-
当封装类与基础类型进行==运算时,封装类会进行拆箱,拆箱结果与基础类型对比值;
-
而两个封装类进行==运算时,与其它的对象的比较一样,对比两个对象的地址,也即判断是否两个引用是否指向同一个对象