作 者: ChanghuiN
前几天和我六哥讨论技术的时候说到了 Integer, 大家可能觉得 Intger 有什么好说的, 不就是 int 吗, Java 装箱拆箱机制. 那么现在有这样一个问题:
- System.out.println(new Integer(1) == (new Integer(1)));
- System.out.println(new Integer(1).equals(new Integer(1)));
- System.out.println(Integer.valueOf(1) == Integer.valueOf(1));
- System.out.println(Integer.valueOf(129) == Integer.valueOf(129));
这四行代码分别输出什么, 为什么?
答案: false,true,true,false
如果你没答出来, 那么请继续往下看吧~
IntegerCache
对, 先说这个类, 一看名字就知道是 Integer 缓存, 它是 Integer 的一个静态内部类. 源码不多, 先看代码:
- private static class IntegerCache {
- static final int low = -128;
- static final int high; // 这个值可以在 vm 属性配置
- static final Integer cache[];
- static {
- ... // 给 high 赋值, 从 vm 属性配置获取配置值, 默认 127
- cache = new Integer[(high - low) + 1];
- int j = low;
- for(int k = 0; k <cache.length; k++)
- cache[k] = new Integer(j++);
- // range [-128, 127] must be interned (JLS7 5.1.7)
- assert IntegerCache.high>= 127;
- }
- }
由上面源码可以看出, IntegerCache 会缓存值为 -128 ~ 127 的 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);
- }
所以当调用 Integer.valueOf 的时候, 如果值在 -128 到 127 的范围, 就会使用 IntegerCache 中的缓存对象.
解答
针对 new Integer(1) == (new Integer(1)), 源码没有做特殊处理, 就是 new 了两个不同的对象, 他们当然是不相等的, 返回 false;
针对 new Integer(1).equals(new Integer(1)), 可以看一下 Integer.equals() 函数的实现, 函数内部是直接比较两个对象的 value 是否相等, 他们的 value 都是 1, 所以返回 true;
针对 Integer.valueOf(1) == Integer.valueOf(1), 就是我们前面提到的 IntegerCache 了, Integer.valueOf 会直接使用缓存好的对象, 两个值相等, 所以对象也是相同的, 返回 true;
针对 Integer.valueOf(129) == Integer.valueOf(129), 由于缓存的范围是 -128 ~ 127, 值 129 显然是超出范围了, 所以会 new 一个新对象, 也不会相等, 返回 false;
装箱拆箱
再看一下以下输出:
- Integer i = 100;
- Integer j = 100;
- System.out.print(i == j); //true
以上例子, Java 在编译是会自动装箱, 编译为: Integer i = Integer.valueOf(100), 又看到了 valueOf, 用了缓存的 Integer, 所以输出 true.
- Integer i = new Integer(100);
- int j = 100;
- System.out.print(i == j); //true
以上例子, 在 int 和 Integer 相比较时, Java 编译器会自动把 Integer 拆箱为 int 类型, 所以输出 100.
拓展
好, 看完了 Integer, 我突然想起了其他的包装器类会不会也是这样, 于是分别看了一下源码.
我直接说结果吧, 有兴趣的同学可以看一下源码: Long,Short 这两个类, 内部也缓存了 -128 ~ 127 的对象, Boolean 内部缓存了 TRUE,FALSE 两个对象. 和 Integer 类似, 都是在调用 valueOf 方法的时候生效, new 的时候不会这样.
关注我们
作 者: ChanghuiN
来源: https://juejin.im/entry/5c749c576fb9a049d132c9e4