一. 经典面试题
在初中级程序员面试中,经常会问到关于对象的保存位置,比如我们一般认为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()方法的源码。
/**
返回表示指定的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),所以如果我们创建的是这个范围内的对象,则会使用常量池中的对象。
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对象的装箱及创建过程,我们才能把上面的这道面试题回答正确。现在你知道这道题该怎么回答了吗?如果还有什么不明白的地方,可以在评论区给老谢留言哦。
最后,请动动你的小手,关注一下Java架构栈,给我们的文章点个赞呗。
五月福利,关注公众号回复【福利】抢书咯!
今日份面试题,学会的同学回复“666”!
精选第一名,可以领取办公鼠标垫一个哦!

点击【阅读原文】,零基础免费学Java!
原文作者:Java架构栈;如有侵权,请联系管理员删除。