一. 经典面试题
在初中级程序员面试中,经常会问到关于对象的保存位置,比如我们一般认为new出来的对象都是存放在堆中,而放在常量池中的对象则不会重复创建,今天老师就来给大家聊聊Integer对象的创建。
题目展现
我们来看下一个面试题:
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;
结果分析
请问在上述代码中r1,r2,r3的值是什么?
如果我们按照原来的思维,这三个对象都指向常量池中的常量,按理说这三个值应该都是true。但正确的结果却是:r1 = true,r2= true,r3=false
二. 题目剖析
这是为什么呢?我们来解析一下
Integer.valueOf()源码
首先str1和str2都指向常量池中同一个字符串常量对象,这没有任何疑义。
其次我们要理解的是,在整数赋值给Integer变量时,它自动做了一个数据装箱,也就是指向Integer.valueOf(整数),自动转化为了Integer对象。我们来看下Integer.valueOf()方法的源码。
/**
返回表示指定的int值的Integer实例。
如果不需要新的Integer实例,则通常应优先使用此方法,而不是构造函数Integer(int) ,因为此方法可能通过缓存频繁请求的值来显着提高空间和时间性能。
此方法将始终缓存-128到127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
*/
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),所以如果我们创建的是这个范围内的对象,则会使用常量池中的对象。
原因分析
接下来我们继续分析上面的面试题代码。
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对象的装箱及创建过程,我们才能把上面的这道面试题回答正确。
相关文章
了解千锋动态
关注千锋教育服务号
扫一扫快速进入
千锋移动端页面
扫码匿名提建议
直达CEO信箱