Integer缓存策略
在 Java 5 中,为 Integer 的操作引入了一个新的特性,用来节省
内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。
下面代码展示Integer的缓存功能(Integer自动装箱):
class="java">public class IntertorTest {
//Integer自动装箱(Integer a = 2;--会变成Integer a = Integer.valueOf(2);)
public static void main(String[] args) {
Integer a = 2;
Integer b = 2;
// a=b:true
System.out.println("a==b:" + (a==b));
// a.equals(b):true
System.out.println("a.equals(b):" + a.equals(b));
Integer c = 200;
Integer d = 200;
// c==d:false
System.out.println("c==d:" + (c==d));
// c.equals(d):true
System.out.println("c.equals(d):" + c.equals(d));
/**
* Java 中,== 比较的是对象引用,而 equals 比较的是值。
*/
}
}
public class IntertorTest {
//使用Integer构造器创建对象。
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(2);
// a=b:false
System.out.println("a==b:" + (a==b));
// a.equals(b):true
System.out.println("a.equals(b):" + a.equals(b));
}
}
上面的规则适用于整数区间 -128 到 +127。这种 Integer 缓存策略仅在自动装箱(autoboxing)的时候有用,使用构造器创建的 Integer 对象不能被缓存。
IntegerCache---Integer的缓存类
IntegerCache是Integer类中一个私有的静态类。我们先看下源代码。
/**
?* 缓存以支持自动装箱的对象身份语义
?* 根据JLS(java语音规范)要求,-128和127(含)。
?*
?* 缓存在初次使用时初始化。
* 缓存的大小可以通过{-XX:AutoBoxCacheMax = <size>}选项进行控制最大值。
?* 在VM初始化期间,java.lang.Integer.IntegerCache.high属性
?* 可以设置并保存在私有系统属性中
?* sun.misc.VM类。
?*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// 高值可能由属性配置
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);
// 最大数组大小为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++);
//范围[-128,127]必须实施(JLS7 5.1.7)
assert Integer.IntegerCache.high >= 127;
}
缓存通过一个for
循环实现。从小到大的创建尽可能多的整数并存储在一个名为 cache的整数数组中。这个缓存会在Integer类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。
JSL(java语言规范如下):
如果一个变量 p 的值属于:-128至127之间的整数(§3.10.1),true 和 false的布尔值 (§3.10.3),’u0000′ 至 ‘u007f’ 之间的字符(§3.10.4)中时,将 p 包装成 a 和 b 两个对象时,可以直接使用 a == b 判断 a 和 b 的值是否相等。
这种缓存行为不仅适用于Integer对象,也适用于其他其他所有的基本类型的包装类型。
我们针对所有整数类型的类都有类似的缓存机制。
有ByteCache用于缓存Byte对象
有ShortCache用于缓存Short对象
有LongCache用于缓存Long对象
有CharacterCache用于缓存Character对象
Byte,Short,Long 有固定范围: -128 到 127。对于Character,范围是 0 到 127。除了 Integer 可以通过
JVM参数改变范围外,其它的都不行。