问题描述如下:
@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数组中的值,由源码分析可以得到下图:
这个故事告诉我们要多多看源码,好了,撸代码去了,就酱