Integer的缓存机制
介绍
Integer首次使用时会初始化缓存,默认情况下,缓存[low, high]范围内的数,low = -128(无法修改),high = 127(默认),可以通过-XX:AutoBoxCacheMax=[size]来指定大小(注意: size一定要大于127,否则high = 127,但是不能大于Integer.MAX_VALUE,否则会报错),max(high) = Integer.MAX_VALUE - (-low) -1。
源码
private static class IntegerCache {
// 缓存最低为-128,不可以修改
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// 默认缓存为127
int h = 127;
// 读取-XX:AutoBoxCacheMax的值
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
// 判断有没有使用-XX:AutoBoxCacheMax修改high的值
if (integerCacheHighPropValue != null) {
try {
// size不能大于Integer.MAX_VALUE,否则会报错
int i = parseInt(integerCacheHighPropValue);
// size一定要大于127,否则白配置
i = Math.max(i, 127);
// max(cache.length) = Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
情况一
new一个Integer对象,直接在堆中创建对象,不使用缓存。
情况二
Integer integer = [value]; //value 为int型
自动装箱操作,若value在[low, high]范围内,则使用缓存,否则相当于情况一。
情况三
调用valueOf方法,底层最终会进行与情况二一样的判断。valueOf(String s)会调用valueOf(int i)。
valueOf(int i)源码
public static Integer valueOf(int i) {
// 判断i是否在缓存范围内,若在返回缓存中的Integer对象,否则返回新创建的Integer对象
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
看了上面的介绍之后,下面的题目应该没有什么问题。
使用默认的缓存范围[-128, 127],请给出以下代码的输出结果。
public class IntegerTest {
public static void main(String[] args) {
// 使用默认的缓存范围[-128, 127]
// 举几个在这个范围内的例子
Integer i1 = new Integer(100);
Integer i2 = 100;
System.out.println("i1 == i2的结果为:" + (i1 == i2));
Integer i3 = new Integer("100");
System.out.println("i2 == i3的结果为:" + (i2 == i3));
Integer i4 = Integer.valueOf(100);
System.out.println("i2 == i4的结果为:" + (i2 == i4));
Integer i5 = Integer.valueOf("100");
System.out.println("i2 == i5的结果为:" + (i2 == i5));
System.out.println("-----------------------");
// 举几个不在这个范围内的例子
Integer i6 = 160;
Integer i7 = Integer.valueOf(160);
System.out.println("i6 == i7的结果为:" + (i6 == i7));
// parseInt方法返回int型,会进行自动装箱,与文中提到的情况二一样
Integer i8 = Integer.parseInt("160");
System.out.println("i6 == i8的结果为:" + (i6 == i8));
}
}
结果如下
i1 == i2的结果为:false
i2 == i3的结果为:false
i2 == i4的结果为:true
i2 == i5的结果为:true
-----------------------
i6 == i7的结果为:false
i6 == i8的结果为:false
使用-XX:AutoBoxCacheMax=[size]来修改缓存范围。
设置size为500。此时范围为[-128, 500] 下面讲一下如何设置,我使用的是IDEA。首先打开Run/Debug Configurations界面(点击Run上的Edit Configurations… 即可。还有其他方法,请自行发现。),然后找到你要修改的类(文中为IntegerTest)。
使用已修改的缓存范围[-128, 500],请给出以下代码的输出结果。
public class IntegerTest {
public static void main(String[] args) {
// -XX:AutoBoxCacheMax=500,即缓存范围为[-128, 500]
// 举几个在这个范围内的例子
Integer i9 = new Integer(200);
Integer i10 = 200;
System.out.println("i9 == i10的结果为:" + (i9 == i10));
Integer i11 = new Integer("200");
System.out.println("i10 == i11的结果为:" + (i10 == i11));
Integer i12 = Integer.valueOf(200);
System.out.println("i10 == i12的结果为:" + (i10 == i12));
Integer i13 = Integer.valueOf("200");
System.out.println("i10 == i13的结果为:" + (i10 == i13));
Integer i14 = 500;
Integer i15 = Integer.valueOf(500);
System.out.println("i14 == i15的结果为:" + (i14 == i15));
System.out.println("-----------------------");
// 举几个不再这个范围内的例子
Integer i16 = -200;
Integer i17 = Integer.valueOf(-200);
System.out.println("i16 == i17的结果为:" + (i16 == i17));
Integer i18 = 501;
Integer i19 = Integer.valueOf(501);
System.out.println("i18 == i19的结果为:" + (i18 == i19));
}
}
结果如下
i9 == i10的结果为:false
i10 == i11的结果为:false
i10 == i12的结果为:true
i10 == i13的结果为:true
i14 == i15的结果为:true
-----------------------
i16 == i17的结果为:false
i18 == i19的结果为:false
嘻嘻,不知道你都答对了吗?如果都答对了,那恭喜你了。如果没有全答对,在思考一下我上面讲的缓存机制。如果你感觉代码中写的例子没有覆盖全部的情况,请自行操作。整篇文章如果有不对的地方,请在评论区留言哦,我会定期查看。希望对你有用。。。