关于IntegerCache的探讨

在importNew上看到了这么一个问题,这次给各位看官分享下。
问题描述如下:
@Test
public void test(){
 Integer s1=100,s2=100;
 Integer c1=1000,c2=1000;
 System.out.println(s1==s2);//true
 System.out.println(c1==c2);//false
}

各位看官可能都知道,Integer为int的封装类型,在使用==比较时,会进行地址比较,那么为何100的时候相等而1000的时候又不相等呢?

首先我们来看看一个小问题,知道答案的看官请保持沉默,让不知道的看官思考下:
对于Integer s1=100;的赋值过程是怎么样的?是调用了构造函数还是怎么样的?
loading.........
下面揭晓答案,这位看官说的很对,是调用了Integer里面的一个方法 valueOf,为了证明这一点,我们使用javap -c Test来看看class文件



可以看出确实是调用了valueOf方法来完成赋值,接着我们来看看Integer中valueOf的源码

public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            //在[-128,127]这个值域的数据,采用缓存
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }


再看看Integer的源码。
 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) {
                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);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }
        private IntegerCache() {}
    }

通过以上源码我们发现,Integer里面包含了一个内部类IntegerCache ,可想而知,其主要功能就是用于缓存值域为[-128,127],当然上限是可以设置的,由于这个区域的数字为常用的数字,故而做此处理来提高效率,节约内存。所以在[-128,127]这个区域里面的数字,数字相同的均指向同一个引用,而在此之外的数字则不会被缓存,从而引用不同,故而得到上述的结果。
接下来,咱们趁热打铁实践下,看看这一段代码,看官们也可以自己试试看。
@Test
public void test(){
        Class cache=Integer.class.getDeclaredClasses()[0];
		Field myCache=cache.getDeclaredField("cache");
		myCache.setAccessible(true);
		Integer[]newCache=(Integer[])myCache.get(cache);
		newCache[132]=newCache[133];
		int a=2;
		int b=a+a;
		System.out.printf("%d + %d = %d", a, a, b);
}

此处我们运用反射来改变cache数组中的值,由源码分析可以得到下图:



这个故事告诉我们要多多看源码,好了,撸代码去了,就酱

猜你喜欢

转载自karenit.iteye.com/blog/2340857
今日推荐