標籤:封裝類 裝箱 拆箱 自動 java
定義
在java中,資料類型可以分為兩大類,即基礎資料型別 (Elementary Data Type)和引用資料類型,基礎資料型別 (Elementary Data Type)的資料不是對象,所以對於要將資料類型作為對象來使用的情況,java提供了相對應的封裝類。(關於封裝類的詳細介紹請參看部落格Java基礎之常用類詳解)
本篇部落客要講述封裝類的自動裝箱和拆行機制。
所謂裝箱,就是把基礎資料型別 (Elementary Data Type)用它們相對應的參考型別包起來,使它們可以具有對象的特質,如我們可以把int類型封裝成Integer類型的對象,或者把double封裝秤Double,等等。
所謂拆箱,就是和裝箱的方向相反,將Integer即Double這樣的參考型別的對象重新簡化成基礎資料型別 (Elementary Data Type)的資料。
而java JDK引入的自動裝箱和拆箱就是編譯器來依據我們編寫的代碼,決定是否進行裝箱和拆箱動作。即無需使用valueOf()和intValue()等方法。(如果這方面不熟悉請參看部落格Java基礎之常用類詳解)
關於自動裝箱拆箱機制的注意事項
這是本篇部落格要講述的重點
先看一個小例子:
public class WrapperText { public static void main(String[] args) { Integer a = 100; Integer b = 100; Integer c = 200; Integer d = 200; System.out.println(a == b);//1 System.out.println(a == 100);//2 System.out.println(c == d);//3 System.out.println(c == 200);//4 }}
如果我們對於Java中自動裝箱和拆箱操作瞭解不夠深入的話,一定會這麼想:自動裝箱後,abcd都是Integer對象的不同引用,“==”操作符又是用來比較對象引用的,所以1和3都應輸出false。而對於2和4,由於a和c都進行了自動拆箱,因此其比較是基礎資料型別 (Elementary Data Type)的比較。“==”操作符比較的使它們的值,所以2和4因該輸出true。即最終結果輸出:
false
true
false
true
但是正確的結果卻是:
我們看到1的結果為true,3的結果為false,這是為什麼呢。其實很簡單,自動裝箱過程其實是調用了valueOf()的方法,而valueOf()方法的源碼為:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } 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() {} }
通過閱讀原始碼,可以發現,java內部為了節省記憶體,IntegerCache類中有一個數組緩衝了值從-128到127的Integer對象。當我們調用Integer.valueOf(int i)的時候,如果i的值時結餘-128到127之間的,會直接從這個緩衝中返回一個對象,否則就new一個新的Integer對象。因此,1為true,3為false。
最後分享一道與之相關的很有意思的題目:
請提供一個對i的聲明,將下面的迴圈轉變成為一個無限迴圈:
while(j <= i && i <= j && i != j){ }
相信如果仔細閱讀了本篇部落格,這道題一定能夠很輕鬆的解決。
Java基礎之封裝類的自動裝箱和拆箱詳解