浅谈IntegerCache

前言

emm,因为之前笔试中遇到了这个问题,当时写的时候是猜的😭,现在好好捋一下为什么。

IntegerCache

先看一下下面的例子,猜猜三个结果。

public  class Main {
    public static void main(String[] args){
        Integer a = new Integer(5);
        Integer b = new Integer(5);
        Integer a1 = 127;
        Integer b1 = 127;
        Integer a2 = 128;
        Integer b2 = 128;

        System.out.println(a==b);
        System.out.println(a1==b1);
        System.out.println(a2==b2);
    }
}

结果

false
true
false

分析

第一组为false,很好理解,因为a和b都是引用不同的实例对象,自然地址不同。
第二组第三组呢,为什么第二组为true,第三组为false呢。这就要涉及到今天要讲的IntegerCache了。
(往下走👇)

源码解析

    // Integer类中含有IntegerCache这样一个内部类

    private static class IntegerCache {
        // 缓存的最低值
        static final int low = -128;
        // 缓存的最高值
        static final int high;
        // 缓存数组
        static final Integer cache[];

        static {
            // high的值是可以通过属性配置的
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            // 如果配置了high的值
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            //初始化缓存数组大小
            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;
        }

        private IntegerCache() {}
    }

那么这个和我们第二组第三组例子有什么关系嘛?👇
我们要先了解自动封装这个概念

    // 当使用Integer a = 数字的时候,其实有一个自动封装的过程
    Integer a = 11;
    // 实际运行时为
    Integer a = Integer.valueOf(11);

我们可以看到,当iIntegerCache的low~high中的时候,那么会直接返回 缓存数组cache 中的Integer。

    public static Integer valueOf(int i) {
        // 如果i处于low~high中
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            // 返回 缓存数组cache 中对应的 Integer
            return IntegerCache.cache[i + (-IntegerCache.low)];
        // 否则new一个新的Integer实例对象
        return new Integer(i);
    }

结论

现在我们就知道了,为什么第二组和第三组一个为true,一个为false。
默认的IntegerCache缓存范围为-128~127
第二组的127是在缓存范围内的a1,b1自动封装获取到的都是同一个Integer,所以结果为true。
第三组128不在缓存范围内,两次自动封装分别new是不同的Integer,所以结果为false。

posted @ 2020-08-21 21:04  jealous-boy  阅读(180)  评论(0编辑  收藏  举报