现在的位置: 首页 > 综合 > 正文

JVM 为什么设置Integer缓存

2020年02月19日 综合 ⁄ 共 1254字 ⁄ 字号 评论关闭

  前段时间在脉脉上看到一位面试官分享出来的一道关于 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);

  这道题目本身没什么难度,主要考察你是不是有好奇心,对平时的工作中经常用到的一些工具类是不是熟悉。要想做对这道题需要知道如下 2 点:

  自动拆装箱

  自动拆装箱就不用多说了,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 为什么设置这个缓存呢?当然是为了性能啦,典型的以空间换时间的策略。

抱歉!评论已关闭.