在JAVA中,在比较两个对象的值是否相等时,我们都知道使用object.equals method,而不能使用"=="操作符进行比较,因为"=="比较的是object的内存地址,通过new创建的object的内存地址是不同的(当然,如果将一个对象指向另一个对象操作另当别论)。
比如:
Integer i1=new Integer(200);
Integer i2=new Integer(200);
此时i1和i2引用了不同的内存区域,所以“i1==i2”的比较结果是false,“i1.equals(i2)”的结果是true。
因为Java使用了7中内置类型,这些内置类型都有与之对应的类,在内置类型可以与其对应的类之间进行自动转换,Java称其为“Autoboxing”。例如:
Integer i3=200;
Integer i4=200;
这次对i3和i4进行比较是遵循上面i1和i2的比较规则的。那么好,再看看下面的例子:
Integer i5=100;
Integer i6=100;
i5和i6进行"=="时的比较结果竟然是true,“i5.equals(i6)”的结果也是true。对于equals导致的放回结果没有什么惊奇,但是为什么"=="的结果是true呢?
这个问题涉及到两个方
面问题:Autoboxing的实现机制和Integer的CacheInteger的机制。
1.Autoboxing的实现机制
Java的Autoboxing的实现机制是在对内置类型对应的类的"="运算符进行了重载,当没有使用new关键字创建对象时,Java就使用Autoboxing方式创建对象,"="重载对应着类的valueOf(parameter) method,parameter为其内置类型,比如Integer的valueOf method的parameter对应的就是内置类型int。这就是Java的Autoboxing的实现机制。
2.Integer的CacheInteger的机制
当理解了Java的Autoboxing机制之后,我们看看Integer的valueOf(int) method是如何实现的。(JDK1.6 Integer.java)
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
从以上代码可以清晰的看到,当没有使用new创建Integer object的时候,如果object的值在-128至127之间,返回的则是一个IntegerCache类的cache数组的一个元素(当然这个元素也是Integer类型的了),而不是new一个Integer object。再来看看IntegerCache是个什么东西。
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
看到这里上面问题的答案已经出来了,原来Java的Integer class中有一个static的IntegerCache class,这个static class中的构造方法中创建了一个cache的Integer array,范围从-128至127。在不使用new关键字创建Integer类型的object的时候,如果这个Integer的范围在-128至127之间,则使用的是Integer的IntegerCache的cache array的一个Integer元素。如果不在这个范围,则调用Integer class的构造方法创建一个Integer object。
所以上面i5和i6都引用了IntegerCache这个static class,这时在使用"=="进行比较的时候,i5和i6当然是相等的了。
研究这个问题是因为在前几次上Java课时,老师将到了这个现象,但是并没有对此进行解决,有的同学怀疑是Java的bug,我感觉不像,因为Java不应该出现如此低级的bug。所以自己进行了一些测试,开始发现这个问题与值的大小有关,将值的范围逐步缩小,发现这个问题只有在-128之127之间有关(正好是1个带符号的byte),当时怀疑是java为了效率问题使用了一个byte表示值比较小的Integer object,但是后来通过debug形式,发现-128至127的Integer object的id竟然使用了一个id,也就是使用了同一个object。再后来就是查看了Integer的源码,再后来就是这篇文章了。
Java内置类型的Autoboxing实现机制和Integer的CacheInteger的使用
最新推荐文章于 2021-03-06 14:47:25 发布