通过1等于2现象加深对 Integer.IntegerCache

2020-11-27  本文已影响0人  上岸大虾米

IntegerCache 是Integer的内部静态类,包含三个字段,主要目的是缓存指定范围[low-high]的整数,low为-128,high的默认值为127,high可通过JVM参数配置修改,high的最小值为127,cache默认缓存了-128~127范围内的整数

 private static class IntegerCache {
        static final int low = -128;
        static final int high; 
        static final Integer cache[];
 }

IntegerCache唯一被Integer.valueOf()方法使用,valueOf()主要是将一个数字赋值给Integer这样的场景使用。例如 Integer a = 3,编译器会将其编译为 Integer a = Integer.valueOf(3)。

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

通过valueOf方法源代码了解到,如果参数i的是在cache范围内,则直接返回被缓存的值,否则创建Integer对象,由此引出经常出现的面试题,因此阿里规范推荐使用equals方法比较Integer值是否相同。

        Integer c1 = 1;
        Integer c2 = 1;
        System.out.println(c1 == c2);   // true

        Integer c3 = 1000;
        Integer c4 = 1000;
        System.out.println(c3 == c4);   // false

缓存部分整形数据,起到复用效果,减少的对象的创建,但是如果随意修改被缓存的值,也会带来一些问题,下面的例子通过修改cache中的值,将会看到 1= 2现象

 public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Class<?>[] declaredClasses = Integer.class.getDeclaredClasses();
        Arrays.stream(declaredClasses).forEach(i -> System.out.println(i.getName()));

        Class<?> declaredClass = declaredClasses[0];
        Field cache = declaredClass.getDeclaredField("cache");
        cache.setAccessible(true);
        Integer[] cacheArr = (Integer[]) cache.get(null);

        System.out.println(cacheArr[129]);
        cacheArr[130] = 1;

        Integer a = 1;
        Integer b = 2;
        System.out.println(a == b);         // true
        System.out.println(a.equals(b));    // true

 }
上一篇下一篇

猜你喜欢

热点阅读