一. 经典面试题
在初中级程序员面试中,经常会问到关于对象的保存位置,比如我们一般认为new出来的对象都是存放在堆中,而放在常量池中的对象则不会重复创建,今天千锋威哥就来给大家聊聊Integer对象的创建。
1.题目展现
我们来看下一个面试题:
String str1 = "千锋教育"; String str2 = "千锋教育"; boolean r1 = str1 == str2; Integer i = 66; Integer ii = 66; boolean r2 = i == ii; Integer i2 = 166; Integer i3 = 166; boolean r3 = i2 == i3;
2.结果分析
请问在上述代码中r1,r2,r3的值是什么?
如果我们按照原来的思维,这三个对象都指向常量池中的常量,按理说这三个值应该都是true。但正确的结果却是:r1 = true,r2= true,r3=false
二. 题目剖析
这是为什么呢?我们来解析一下
1.Integer.valueOf()源码
首先str1和str2都指向常量池中同一个字符串常量对象,这没有任何疑义。
其次我们要理解的是,在整数赋值给Integer变量时,它自动做了一个数据装箱,也就是指向Integer.valueOf(整数),自动转化为了Integer对象。我们来看下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);
}
从上面的源码中,我们可以看到,常量池会缓存256个Integer对象,值的范围是(-128-127),所以如果我们创建的是这个范围内的对象,则会使用常量池中的对象。
2.原因分析
接下来我们继续分析上面的面试题代码。
Integer i = 66; //使用常量池中常量对象 //Integer i = Integer.valueOf(66); Integer ii = 66; //使用常量池中常量对象 //Integer ii = Integer.valueOf(66); boolean r2 = i == ii; Integer i2 = 166; //在堆中重新创建对象 //Integer i2 = Integer.valueOf(166); Integer i3 = 166; //在堆中重新创建对象 //Integer i3 = Integer.valueOf(166); boolean r3 = i2 == i3;
这时我们就可以得出结论,i和ii两个变量都指向常量中的同一个对象,所以r2的结果为true。
根据我们上面分析的Integer.valueOf()源码可知,在定义i2和i3两个变量时,都会在堆中重新创建一个Integer对象,故而r3的结果是false。
所以只有深入理解Integer对象的装箱及创建过程,我们才能把上面的这道面试题回答正确。现在你知道这道题该怎么回答了吗?如果还有什么不明白的地方,可以在评论区给威哥留言哦。



