在了解 Integer 的缓存机制之前,先了解一下装箱和拆箱。
Integer --> int 拆箱 intValue();
int --> Integer 装箱 valueOf();
一、什么时候触发装箱、拆箱?
1.1 装箱
将一个 int 的数值,赋值给一个 Integer 引用会触发装箱过程。如:
Integer a = 10; //等价于 Integer a = Integer.valueOf(10);
由于10为 int 类型,在赋值给 a 时,会先调用 valueOf() 方法从缓存中取出一个 Integer 对象或者创建一个值为 10 的 Integer 对象(valueOf() 方法后面具体再详述)。
1.2 拆箱
① 将一个 Integer 的包装类型对象赋值给 int 类型的变量,如:
Integer a = 10; //上面说到,该语句会触发装箱过程,返回一个 Integer 对象
int b = a; //将 Integer 类型变量赋值给 int 类型变量,会触发拆箱过程
//等价于 int b = a.intValue(); 直接返回一个 int 的值
② 进行运算符运算时
Integer a = 10;
Integer b = 20;
System.out.println(a * b);//触发拆箱过程,等价于 a.intValue() * b.intValue()
注意:当进行 == 运算时,若两个数据类型都为 Integer 时,它们将直接比较这两个 Integer 对象是否一样;若有一个数据类型为 int ,另外一个数据类型为 Integer 时,Integer 的数据将进行拆箱转换为 int,然后再进行比较值是否相等。如:
Integer a = 10;
Integer b = 10;
int c = 10;
System.out.println(a == b); //等价于 Integer.valueOf(10) == Integer.valueOf(10) ; true
System.out.println(a == c); //等价于 a.intValue() == c true
二、Integer 缓存机制
当在进行装箱操作时,需要装箱的值的大小处于 -128 到 127 时,调用 Integer.valueOf() 方法将会从缓存中直接取出已经预先创建好的 Integer 对象;当数值不处于 【-128,127】区间时,将会直接 new Integer();进行新创建一个对象。
查看 Integer 的 valueOf() 方法的源码:
public static Integer valueOf(int i) {
// IntegerCache.low = -128, IntegerCache.high = 127
if (i >= IntegerCache.low && i <= IntegerCache.high)
// cache 是一个存放着值为 -128 到 127 的 Integer 数组
//从缓存数组直接取对应的 Integer 对象
return IntegerCache.cache[i + (-IntegerCache.low)];
//数值不在 [-128, 127] 区间,直接 new 一个 Integer 对象
return new Integer(i);
}
查看 IntegerCache 类源码(Integer 的缓存类):
private static class IntegerCache {
static final int low = -128;
static final int high;
//缓存数组,用来存放 -128 到 127 的 Integer 对象
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
// high = 127
high = h;
// 创建一个大小为 256 的 Integer 对象数组
cache = new Integer[(high - low) + 1];
// low = -128
int j = low;
// 从 -128 开始到 127 结束,每个数值创建一个 Integer 对象,并把该对象放置到 cache 数组中
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
IntegerCache 类是 Integer 的一个内部类,该类的主要功能是存储 [-128, 127] 范围的 Integer 对象。
验证:
Integer a = 10;
Integer b = 10;
Integer c = 128;
Integer d = 128;
System.out.println(a == b); //true
System.out.println(c == d) //false
a == b 的结果为 true 是因为它们都会进行装箱,调用 valueOf() 方法,且大小在 [-128, 127],直接从缓存数组中直接取出,取出的 Integer 对象是同一个对象,所以 a == b 为 true
c == d 的结果为 false,是因为其值不在 [-128, 127] 范围内,会直接 new 一个 Integer 对象(每new 一个对象,它们就会内存的不同位置创建对象)