現象描述
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true(引用相同,從緩存中取)Integer c = 200;
Integer d = 200;
System.out.println(c == b); // false(超出緩存范圍,new Integer(200))
原因分析
Integer從Java 5開始,引入了緩存機制,用于緩存一定范圍內的Integer對象。
- 默認緩存范圍是-128~127
- 這些值對應的Integer對象在JVM啟動時就被創建,并緩存在內存中
Integer緩存與JVM的關系
Integer中有一個靜態內部類
private static class IntegerCache {static final int high;static final Integer cache[];static {final int low = -128;// high value may be configured by propertyint h = 127;if (integerCacheHighPropValue != null) {// Use Long.decode here to avoid invoking methods that// require Integer's autoboxing cache to be initializedint i = Long.decode(integerCacheHighPropValue).intValue();i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - -low);}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() {}}
從JVM初始化的配置中獲取integerCacheHighPropValue
,如果大于127,那么初始化的最大值就是integerCacheHighPropValue
cache數組的個數是hight-low+1
在cache中初始化從low到high的數字
public static Integer valueOf(int i) {if(i >= -128 && i <= IntegerCache.high)return IntegerCache.cache[i + 128];elsereturn new Integer(i);}
當調用Integer.valueOf
的時候,如果i的范圍在-127~IntegerCache.high
,就直接從緩存中取。因為是從緩存中直接獲取的,所以即使多次獲取,對象的內存地址是相同的。
但是如果i不在這個范圍內,那么回返回一個新的對象,這時即使i的數字相同,但多個對象的內存地址不同。用==
來比較,結果會是false
.
編碼
Integer a = 200;
Integer b = 200;
int c = 200;// ? 危險:結果依賴緩存
System.out.println(a == b); // false// ? 安全:比較值
System.out.println(a.equals(b)); // true// ? 安全高效
System.out.println(a == c); // true(拆箱比較)// ? 最安全(推薦)
System.out.println(Objects.equals(a, b)); // true
Integer
VSInteger
:必須用equals()
或Object.equals
- Integer VS int:用
==
更安全、更高效 - 為了避免null的問題,有限使用
Objects.equals(a,b)