1.介紹
關於Integer和int在面試的時候出現的頻率很高。而我們所熟知的是Integer是int 的包裝類型,int的初始值爲0,Integer的初始值爲null,這是基本都知道的。至於Integer的自動裝箱和拆箱,以及Integer的緩存等小細節需要深入思考。
2.包裝類的裝箱和拆箱
從基本數據類型到包裝類型的過程是裝箱、從包裝類型到基本數據類型的過程是拆箱。
例子:
public static void main(String[] args) {
//標準的裝箱過程
Integer i =new Integer(127);
/**
* 這個寫法相當於Integer i1 =new Integer(127);
* 這個初始化的過程默認也是使用了自動裝箱
* 裝箱的本意就是將基本數據類型轉換成包裝類型
* */
Integer i1 =127;
//標準的拆箱過程
int j =i.intValue();
/**
* 這個寫法相當於int j1 =i1.intValue();
* 這個初始化的過程默認也是使用了自動拆箱過程
* 拆箱的本意就是將包裝類型轉換成基本數據類型
* */
int j1 =i1;
}
int(4字節) | Integer |
byte(1字節) | Byte |
short(2字節) | Short |
long(8字節) | Long |
float(4字節) | Float |
double(8字節) | Double |
char(2字節) | Character |
boolean(未定) | Boolean |
3.Integer的緩存
Integer定義了一個靜態內部類IntegerCache作爲緩存
緩存源碼:
private static class IntegerCache {
//常量最小值-128
static final int low = -128;
//常量最大值
static final int high;
//Integer緩存數組
static final Integer cache[];
static {
//初始化h變量爲127
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
//說明i最小可以取到127,規定了i的下限,所以i>=127
i = Math.max(i, 127);
//由於i>=127並且Integer.MAX_VALUE - (-low)>128,因此可以得到h>=127
h = Math.min(i, Integer.MAX_VALUE - (-low));
}
high = h;
//初始化Integer緩存數組
cache = new Integer[(high - low) + 1];
//數組中的初始值是-128
int j = low;
//循環爲數組賦值,數組0位是-128,最大是127(臨界值)
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
/**
* 返回一個表示指定的 int 值的 Integer 實例。
* 如果不需要新的 Integer 實例,則通常應優先使用該方法,而不是構造方法 Integer(int)
* 因爲該方法有可能通過緩存經常請求的值而顯著提高空間和時間性能
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
//當-128<=i<=127時,直接從緩存數組中取出值
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
//否則返回新的Integer對象
return new Integer(i);
}
而我們使用Integer i=100的時候採取的裝箱操作實際上調用了valueof方法,API也提示儘量多使用valueof的方式創建Integer的實例而不是以new Integer的方式。因爲valueof方式使用緩存提高空間的利用率和時間性能。
4.經典面試題
public static void main(String[] args) {
//標準的裝箱過程
Integer i =new Integer(100);
Integer i1 =100;
Integer i2 =100;
Integer i3 =128;
Integer i4 =128;
System.out.println("i==i1 :"+(i==i1));
System.out.println("i1==i2 :"+(i1==i2));
System.out.println("i3==i4 :"+(i3==i4));
}
打印結果:
解釋:
(1) i == i1 :由於i本身是new Integer的方式單獨開闢空間,i1是 -128<=i1<=127,所以i1是從緩存中取出數據的。而緩存的地址和new Integer單獨開闢空間對應的地址不同,返回false。
(2) i1 == i2 :i1是 -128<=i1<=127,所以i1是從緩存中取出數據的。i2是-128<=i2<=127,所以i2也是從緩存中取出數據的。所以i1和i2對應的是同一個緩存地址,返回true。
(3)i3 == i4 :i3>127並且i4>127,所以i3和i4分別是new Integer這種單獨開闢空間,地址不同,返回false。