細節問題2:Integer什麼時候會使用常量池裏的值什麼時候會new一個?
package classandobject;
public class Integer_Int {
public static void main(String[]args){
// 1)基本類型和包裝類型
int a = 100;//常規量,
Integer b = 100;//自動裝箱,但是100在-128到127之間,使用常量池存放,不用new一個
System.out.println(a == b);//b拆箱,這裏就是比較值的大小了。
// 2)兩個包裝類型
Integer c = 100;//自動裝箱,但是100在-128到127之間,沒有使用new,默認放在棧裏邊,是地址引用,100存儲在方法區的常量池中
Integer d = 100;//自動裝箱,但是100在-128到127之間,沒有使用new,默認放在棧裏邊,是地址引用,100存儲在方法區的常量池中
System.out.println(c == d);//true,地址引用相同
System.out.println(c==a);//true 自動拆箱
Integer c_new = new Integer(100);
System.out.println(c_new==c);//false,因爲地址引用不同
// 3)常規量
c = 200;//c = c.valueOf(200),200不在-128到127之間,所以會使用new創建對象
d = 200;//也就是說這裏c,d都使用了new,
System.out.println(c == d);//使用new創建的對象地址引用不同,false
System.out.println(c.equals(d));//比較的是值,true
}
}
解析
之前我們已經知道了,自動裝箱是通過 Integer.valueOf() 完成的,那我們就來看看這個方法的源碼吧。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)//low=-128,high = 127
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);//發現沒有,裝箱過程可能會用到new
}
//我們來看一下條件是什麼:
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;
int i = parseInt(integerCacheHighPropValue);//
i = Math.max(i, 127);
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);//基本都是h = i了。。。
high = h;//high = i;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
}
valueOf() 方法的實現比較簡單,就是先判斷值是否在緩存池中,如果在的話就直接返回緩存池的內容。在 Java 8 中,Integer 緩存池的大小默認爲 -128~127。編譯器會在自動裝箱過程調用 valueOf() 方法,因此
多個值相同且值在緩存池範圍內(-128~127)的 Integer 實例使用自動裝箱來創建,那麼就會引用相同的對象。