JDK1.5以前,建立Integer對象是須要這麼寫的 Integer i = new Integer("3");java
JDK1.5以後,有了自動裝箱,建立Integer對象時,咱們能夠這樣寫 Integer i = 5;編程
1 int num = 3; 2 num = num + 4;
3 //這樣寫在JDK1.5中是沒有問題的 4 Integer x = 3; 5 x = x + 4;
這樣以來Integer就擁有了和 int 基本類型同樣的能力。表面看起來對象變的能夠直接進行運算,這對編程來講方便了不少。數組
由 Integer x = new Integer(3); 簡化成:Integer i = 3; 能夠理解爲java自動幫咱們作了 x = new Integer(3)的操做。緩存
x = x + 4; 對象是不能直接用來進行運算的,因此java會自動的作拆箱的操做,把(x+4)中的 x 自動拆箱(也就是調用Integer的intValue()方法,把x轉換爲int類型進行運算),當運算完成以後會把運算結果再次使用裝箱賦值給 x 。【整個表達式先拆箱運算完成以後再裝箱】ide
1 Integer a = new Integer(127); 2 Integer b = new Integer(127); 3 System.out.println(a==b);//false 4 System.out.println(a.equals(b));//true 5 6 Integer c = 127;//JDK1.5之後,自動裝箱若是裝箱的是一個字節那麼該數據會被共享 不會從新開闢空間 7 Integer d = 127; 8 System.out.println(c==d);//true 9 System.out.println(c.equals(d));//true
經過測試上面代碼的測試結果看出,JDK1.5之後Integer自動裝箱的數據若是是一個字節,那麼該數據會被共享,不會從新開闢新的空間。性能
這就與咱們上面說的裝箱拆箱操做相矛盾了,若是Integer x = 3 真的代替了 Integer x = new Integer(3); 這裏已經使用了new,怎麼可能會不開闢新的空間呢?測試
若是不開闢空間的話,那麼共享數據總要存在於一塊共享空間以內,難道會像字符串那樣維護了一個常量池?ui
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 -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 int i = parseInt(integerCacheHighPropValue); 24 i = Math.max(i, 127); 25 // Maximum array size is Integer.MAX_VALUE 26 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 27 } 28 high = h; 29 30 cache = new Integer[(high - low) + 1]; 31 int j = low; 32 for(int k = 0; k < cache.length; k++) 33 cache[k] = new Integer(j++); 34 } 35 36 private IntegerCache() {} 37 }
經過查找源碼發現,原來Integer類內部維護了一個靜態內部類,這是JDK1.5中,爲 Integer 的操做引入了一個新的特性,用來節省內存和提升性能。整型對象在內部實現中經過使用相同的對象引用實現了緩存和重用。this
Javadoc 詳細的說明這個類是用來實現緩存支持,並支持 -128 到 127 之間的自動裝箱過程。最大值 127 能夠經過 JVM 的啓動參數 -XX:AutoBoxCacheMax=size 修改。 緩存經過一個 for 循環實現。從小到大的建立儘量多的整數並存儲在一個名爲 cache 的整數數組中。這個緩存會在 Integer 類第一次被使用的時候被初始化出來。之後,就可使用緩存中包含的實例對象,而不是建立一個新的實例(在自動裝箱的狀況下)。spa
經過查看Integer的構造方法發現,沒有一個構造方法會從IntegerCache中取值,很顯然自動裝箱的操做並非經過new Integer()來完成的。應該是經過其餘的方法!
1 /** 2 * Returns an {@code Integer} instance representing the specified 3 * {@code int} value. If a new {@code Integer} instance is not 4 * required, this method should generally be used in preference to 5 * the constructor {@link #Integer(int)}, as this method is likely 6 * to yield significantly better space and time performance by 7 * caching frequently requested values. 8 * 9 * This method will always cache values in the range -128 to 127, 10 * inclusive, and may cache other values outside of this range. 11 * 12 * @param i an {@code int} value. 13 * @return an {@code Integer} instance representing {@code i}. 14 * @since 1.5 15 */ 16 public static Integer valueOf(int i) { 17 assert IntegerCache.high >= 127; 18 if (i >= IntegerCache.low && i <= IntegerCache.high) 19 return IntegerCache.cache[i + (-IntegerCache.low)]; 20 return new Integer(i); 21 }
經過查看源碼發現valueOf(int i)【只有這一個方法,其餘的重載方法未操做IntegerCache】中出現了對IntegerCache的操做。看源碼咱們瞭解到若是傳入的-128<i<127 就會從IntegerCache的cache數組中取出共享數據,若是不在這個範圍以內則使用new Integer(i)。
由此也就完全明白了裝箱拆箱的內幕!
> 裝箱使用的是valueOf(int i)
> 拆箱使用的是intValue();
其實這種緩存行爲不只適用於Integer對象,針對全部整數類型的類都有相似的緩存機制。
有 ByteCache 用於緩存 Byte 對象
有 ShortCache 用於緩存 Short 對象
有 LongCache 用於緩存 Long 對象
有 CharacterCache 用於緩存 Character 對象
Byte、Short、Long有固定範圍:-128~127,對於 Character範圍是:0~127。
除了Integer能夠經過參數改變範圍外,其餘對象都不能夠。