1 public class IntegerTest { 2 public static void main(String[] args) { 3 Integer a = 10; 4 Integer b = 10; 5 System.out.println(a==b); 6 7 Integer c = 1000; 8 Integer d = 1000; 9 System.out.println(c==d); 10 } 11 }
上面这段代码输出:
true false
纳尼?不都是引用比较吗?值相等,引用不相等,应该都返回false吧?别着急,我们下面分析一下。
原因:在 Java 5 中,为 Integer 的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。对整数区间 -128 到 +127的整数都做了缓存,到Java 8开始缓存范围改为-128 到 N。其中N为可配置参数。
再看一段代码:
1 public class IntegerTest { 2 public static void main(String[] args) { 3 Integer a1 = new Integer(10); 4 Integer b1 = new Integer(10); 5 System.out.println(a1==b1); 6 } 7 }
这个输出结果是什么呢?估计你们已经猜到了,既然让我们猜肯定是false啊。不然还猜个屁!没错答案就是false。为什么呢?
原因:这种 Integer 缓存策略仅在自动装箱(autoboxing)的时候有用,使用构造器创建的 Integer 对象不能被缓存。
自动装箱,拆箱不懂?自己另行百度吧。
看下一下Integer缓存实现的源码IntegerCache类:
支持 -128 到 127 之间的自动装箱过程。最大值 127 可以通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改。初始化的时候通过for循环将-128到AutoBoxCacheMax之间的数组装载到cache数组。
1 /** 2 * Cache to support the object identity semantics of autoboxing for values between 3 * -128 and 127 (inclusive) as required by JLS. 4 * 5 * The cache is initialized on first usage. The size of the cache 6 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. 7 * During VM initialization, java.lang.Integer.IntegerCache.high property 8 * may be set and saved in the private system properties in the 9 * sun.misc.VM class. 10 */ 11 12 private static class IntegerCache { 13 static final int low = -128; 14 static final int high; 15 static final Integer cache[]; 16 17 static { 18 // high value may be configured by property 19 int h = 127; 20 String integerCacheHighPropValue = 21 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 22 if (integerCacheHighPropValue != null) { 23 try { 24 int i = parseInt(integerCacheHighPropValue); 25 i = Math.max(i, 127); 26 // Maximum array size is Integer.MAX_VALUE 27 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 28 } catch( NumberFormatException nfe) { 29 // If the property cannot be parsed into an int, ignore it. 30 } 31 } 32 high = h; 33 34 cache = new Integer[(high - low) + 1]; 35 int j = low; 36 for(int k = 0; k < cache.length; k++) 37 cache[k] = new Integer(j++); 38 39 // range [-128, 127] must be interned (JLS7 5.1.7) 40 assert IntegerCache.high >= 127; 41 } 42 43 private IntegerCache() {} 44 }
再来看一下Integer的valueof()方法:
1 public static Integer valueOf(int i) { 2 if (i >= IntegerCache.low && i <= IntegerCache.high) 3 return IntegerCache.cache[i + (-IntegerCache.low)]; 4 return new Integer(i); 5 }
从上面的代码可以看到每次通过valueOf做装箱的时候,都会判断int i是否在-128到127之间。在的话直接从cache数组取出来返回。所以,
Integer a = 10;
Integer b = 10;
a和b返回的都是IntegerCache.cache[138]这个引用,最后做==比较的时候自然结果为true。