1. 程式人生 > >JDK1.8 Integer,Long等的快取策略

JDK1.8 Integer,Long等的快取策略

 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。