Java JDK源码中有很多小惊喜在等着我们,我们需要多多阅读它。对于一件事我们要做到知其然知其所以然。下面就是其中的一个小例子。今天在群里面遇到一个问题,代码如下。
public class IntegerCacheTest {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1 == i2);
}
}
运行结果如下:
我们都知道在Java中使用==是比较引用地址,但是Integer作为包装对象,应该有不同的地址。为什么这里它的地址是一样的呢?首先要解决这个问题我们先要知道基本类型与Java 自动装箱与拆箱(Autoboxing and unboxing).但i1与i2进行比较的时候作为类型为int的值100会自己装箱为Integer.也就是Integer.valueOf(100).那么我们就到JDK源码中看看Integer类的valueOf(int)
方法。代码如下:
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
我们int的值为100,如果不进入if条件就会返回一个新的Integer对象。那么比较就会返回false。然后再结合IntegerCache这个词,关键是不是因为它呢?然后我们再看看IntegerCache这个类,这个类是Integer的内部类。我们首先来看一看这个类的说明。
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the -XX:AutoBoxCacheMax= option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
这个方法的说明的大概意思是当第一次自动装箱的时候会自动生成支持(-128 - 127)这个范围的值的Integer的Cache.然后你可以通过指定-XX:AutoBoxCacheMax=<size>
值指定cache的最大值。下面我们来看一下具体是怎么实现的。
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) {
// 获取这个值与127更大的一个
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// 这里是确保下面创建缓存数组的最大Size为Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
// 设置缓存的最大值
high = h;
// 创建这个缓存数据,
cache = new Integer[(high - low) + 1];
int j = low;
// 初始化这个Integer的缓存数组
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
其实在Long中也能找到类似的代码。