问题 11
前段时间在脉脉上看到一位面试官分享出来的一道关于 Integer 的面试题目,当时看了以后心里有点犹豫,知道 Integer 有缓存,但是这道题目还是做的有些犹豫,于是仔细琢磨了一下这道题目,分享给大家。题目如下,要求回答出输出结果,并说明为什么?
int a = 1;
Integer b = 1;
Integer c = 1;
Integer d = Integer.valueOf(1);
Integer e = new Integer(1);
Integer f = new Integer(1);
Integer g = 128;
Integer h = Integer.valueOf(128);
System.out.println(a == b);
System.out.println(b == c);
System.out.println(c == d);
System.out.println(d == e);
System.out.println(e == f);
System.out.println(g == h);
我的答案
这道题目本身没什么难度,主要考察你是不是有好奇心,对平时的工作中经常用到的一些工具类是不是熟悉。要想做对这道题需要知道如下几点:
自动拆装箱
自动拆装箱就不用多说了,int 赋值给 Integer 的时候会发生自动装箱操作,Integer 赋值给 int 的时候回发生自动拆箱操作。在 a == b 的表达式中,b 发生了自动拆箱操作转换为了它对应的 int 值。因此 a == b 输出为 true。在赋值语句 Integer b = 1 出现的时候发生了自动装箱操作,这个装箱操作实际使用了 Integer 的静态工厂方法 Integer.valueOf(),然后得到一个 Integer 对象。既然是这样,那么 b == c,显然输出 true。d 直接使用了工厂方法来构造,很明显 c == d 会输出 true。
缓存
接下来就比较好玩了,我们使用 new 初始化出来的对象和使用工厂方法构造出来的对象相等吗?如果你看过 Integer 的源码你会知道,他俩是不相等的。我们都知道 == 比较的是对象的地址,有些人知道 Integer 有缓存功能,误认为使用 new 初始化 Integer 对象的时候也使用了缓存。然而并不是,只有在使用了 Integer 静态工厂方法时候才会使用 Integer 的缓存对象。由此我们可以得出 d == e 会输出 false,e == f 也会输出 false。
g 和 h 的比较在考察 Integer 缓存的大小了,默认情况下 JVM 缓存的整数大小是 -128 - 127,这个大小我们是可以通过参数更改的,例如我们让他可以缓存 -128 - 200 的整数,可以给 JVM 设置如下参数:
-XX:AutoBoxCacheMax=128
如果添加了如上的参数设置,那么 g == h 会输出 true,因为他们都使用了事先初始化好的缓存对象。假设使用了默认的 JVM 参数配置,那么会输出 false,因为他们会被构造为 2 个不同的对象。那么 JVM 为什么设置这个缓存呢?当然是为了性能啦,典型的以空间换时间的策略。
以上就是我对于 Integer 的理解啦,小伙伴们赶紧去学习一下,有问题可以和我讨论哦。
以上即为昨天的问题的答案,小伙伴们对这个答案是否满意呢?欢迎留言和我讨论。
又要到年末了,你是不是又悄咪咪的开始看机会啦。为了广大小伙伴能充足电量,能顺利通过 BAT 的面试官无情三连炮,我特意推出大型刷题节目。每天一道题目,第二天给答案,前一天给小伙伴们独立思考的机会。