一、裝箱、拆箱定義
如果一個int型量被傳遞到需要一個Integer對象的地方,那么,編譯器將在幕后插入一個對Integer構造方法的調用,這就叫做自動裝箱。而如果一個Integer對象被放到需要int型量的地方,則編譯器將幕后插入一個隊intValue方法的調用,這就叫做自動拆箱。
public static voidmain(String[] args) {//裝箱
Integer i1 = Integer.valueOf(1);//自動裝箱
Integer i2 = 1;//默認執行valueOf(1);
System.out.println(i1 == i2);//true
//自動拆箱
int i3 =i1.intValue();int i4 =i2.intValue();
System.out.println(i3== i4);//true
//超出Integer的緩存范圍,不從私有靜態內部類IntegerCache的數組cache中獲得,通過new返回新對象
Integer i5 = 128;
Integer i6= -129;
Integer i5_1= 128;
Integer i6_1= -129;
System.out.println(i5== i5_1);//false
System.out.println(i6 == i6_1);//false
}
所以說,對于-127~127之間的值,Integer對象中存在一個IntegerCache的私有靜態內部類,這個內部類有一個Integer類型的靜態常量數組,在這個內部類中通過靜態方法塊,初始化了這個靜態常量數組。默認這個數組保存[-127,128)之間的Integer對象。源碼如下:
1 private static classIntegerCache {2 static final int low = -128;3 static final inthigh;4 static finalInteger cache[];5
6 static{7 //high value may be configured by property
8 int h = 127;9 String integerCacheHighPropValue =
10 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");11 if (integerCacheHighPropValue != null) {12 try{13 int i =parseInt(integerCacheHighPropValue);14 i = Math.max(i, 127);15 //Maximum array size is Integer.MAX_VALUE
16 h = Math.min(i, Integer.MAX_VALUE - (-low) -1);17 } catch( NumberFormatException nfe) {18 //If the property cannot be parsed into an int, ignore it.
19 }20 }21 high =h;22
23 cache = new Integer[(high - low) + 1];24 int j =low;25 for(int k = 0; k < cache.length; k++)26 cache[k] = new Integer(j++);27
28 //range [-128, 127] must be interned (JLS7 5.1.7)
29 assert IntegerCache.high >= 127;30 }31
32 privateIntegerCache() {}33 }
通過下面的源碼可以知道,為什么Integer i = 128;與Integer y = 128;,通過==比較的結果為false。如果要賦值的int變量在范圍內,則返回數組中的對象給Integer,如果不在,則通過帶參構造方法,new一個新的Integer對象。
1 public static Integer valueOf(inti) {2 if (i >= IntegerCache.low && i <=IntegerCache.high)3 return IntegerCache.cache[i + (-IntegerCache.low)];4 return newInteger(i);5 }
二、其它包裝類型
The Java Language Specification, 3rd Edition 寫道:
為了節省內存,對于下列包裝對象的兩個實例,當它們的基本值相同時,他們總是==:
Boolean :全部緩存
Byte :全部緩存
Character : <=127緩存
Short : (-128,127)緩存
Long : (-128,127)緩存
Float : (沒有緩存)
Double : (沒有緩存)
其中Character的緩存源碼:
1 private static classCharacterCache {2 privateCharacterCache(){}3
4 static final Character cache[] = new Character[127 + 1];5
6 static{7 for (int i = 0; i < cache.length; i++)8 cache[i] = new Character((char)i);9 }10 }
其中Float沒有緩存,直接返回源碼:
1 public static Float valueOf(String s) throwsNumberFormatException {2 return newFloat(parseFloat(s));3 }
三、用處
除了包裝類提供了額外的方法外,當使用集合框架時,泛型為Object類型,所以如果聲明為List list...,則這樣是不行的,必須聲明為List list...。
四、存儲的位置
因為是對象,所以存儲在堆中。