JDK1.8 Integer,Long等的快取策略
阿新 • • 發佈:2018-11-01
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 = newInteger(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。