Integer缓存

之前在看一些java基础的面试题中,出现了一个Integer 自动封装及解封的相关问题。写如下代码:

public class MainClass {
    public static void main(String[] args)
    {
        Integer int1 = Integer.valueOf(128);
        Integer int2 = Integer.valueOf(128);
        Integer int3 = Integer.valueOf(23);
        Integer int4 = Integer.valueOf(23);
        Integer int5 = int1;
        System.out.println(int1 == int2);
        System.out.println(int1 == 128);
        System.out.println(int3 == int4);
        System.out.println(int3 == 23);
    }
}

得出结果:
false
true
true
true

在没看过源码的情况下会觉得比较奇怪。翻阅Integer源码会发现,Integer有一个IntegerCache内部类,默认会对 -128 到 127 之间的数进行缓存。另外我们还可以在JVM参数中设置 -XX:AutoBoxCacheMax=<size> 来设置缓存的范围,size的范围需要在128至 Integer.MAX_VALUE - (-low) -1。这样缓存的数是-128至size和(Integer.MAX_VALUE - (-low) -1)中较小的一个。

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

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.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.valueOf(int i),方法实现如下:

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() 方法来获取一个Integer时,如果在我们的缓存区域内,就会直接从缓存中的对象获取。于是有System.out.println(int3 == int4) 输出为true,而System.out.println(int1 == int2)为false。
对开篇是代码进行调试,在进程结束前打上断点:


捕获.PNG

我们可以看到,int1和int2 值相同,但对应的并不是同一个地址@502及@503,因为Integer是对象类型,而不是基本类型,对其进行的 == 操作是判断这两个对象是不是指向同一个对象,因此返回为false。而int3和int4则是指向了同一个对象@504,对他们进行
== 操作返回为true。

至于自动解封的情况,应该是确切的需要接受基本类型的时候才会出现,我们的int5=int1操作中,我们的左值是一个Integer对象类型,而不是一个基础类型,所以直接将int5指向了int1,为同一个对象。

至于为什么要设计这样的缓存机制,尚未深究,后续如果有时间,研究一下JSLJVMS后看能否找到答案。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容