缓冲池IntegerCache
Integer中有个静态内部类IntegerCache,里面有个cache[],也就是Integer常量池,常量池的大小为一个字节(-128~127)。
源码为(jdk1.8.0_101)
private static class IntegerCache {
static final int low = -128;
static final int high;
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 = h;
cache = new Integer[(high - low) + 1];
int j = low;
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() {}
}
当创建Integer对象时,不使用new Integer(int i)语句,大小在-128~127之间,对象存放在Integer常量池中。
例如:Integer a = 10;
调用的是Integer.valueOf()方法,代码为
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
这也是自动装箱的代码实现。
测试Integer的特性:
public class TestInteger {
public static void main(String[] args) {
//jdk1.5后 虚拟机为包装类提供了缓冲池,Integer缓冲池的大小为一个字节(-128~127);
//创建 1 个对象,存放在常量池中。引用c1,c2存放在栈内存中。
Integer c1 = 1;
Integer c2 = 1;
System.out.println("c1 = c2 ? " + (c1 == c2)); //true
//创建 2 个对象,存放在堆内存中。2 个引用存放在栈内存中。
Integer b1 = 130; //130不在(-128~127)之间
Integer b2 = 130;
System.out.println("b1 = b2 ? " + (b1 == b2)); //false
//创建2个对象,存放在堆内存中。
Integer b3 = new Integer(2);
Integer b4 = new Integer(2);
System.out.println("b3 = b4 ? " + (b3 == b4)); //false
//下面两行代码证明了使用new Integer(int i) (i 在-128~127之间)创建对象不会保存在常量池中。
Integer b5 = 2;
System.out.println("b3 = b5 ? " + (b3 == b5)); //false
//Integer的自动拆箱,b3自动转换成数字 2。
System.out.println("b3 = 2 ? " + (b3 == 2)); //true
Integer b6 = 210;
System.out.println("b6 = 210 ? " + (b6 == 210)); //true
}
}
打印结果为:
c1 = c2 ? true
b1 = b2 ? false
b3 = b4 ? false
b3 = b5 ? false
b3 = 2 ? true
b6 = 210 ? true
其他缓存的对象
这种缓存行为不仅适用于Integer对象。我们针对所有整数类型的类都有类似的缓存机制。
有 ByteCache 用于缓存 Byte 对象
有 ShortCache 用于缓存 Short 对象
有 LongCache 用于缓存 Long 对象
有 CharacterCache 用于缓存 Character 对象
Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 可以通过参数改变范围外,其它的都不行。
建议:所有相同类型的包装类对象之间值得比较,全部使用equals方法。