今天研究了Interger的源碼,看了源碼後才知道根本,以前做過的關于interger的面試題都迎刃而解。
今天以面試題為引子
Integer a5=128;
Integer a6=128;
Integer a7=127;
Integer a8=127;
Integer a9=new Integer(127);
System.out.println(a5==a6);//false
System.out.println(a7==a8);//true
System.out.println(a9==a8);//false
System.out.println(a9.equals(a8));在程式中運作 jdk1.7的環境下 是false,大家都知道 == 比對的位址的引用(不知道的話可以自行去搜尋下,網上很多的例子)
通過上面可以得到 a8 和 a9的數值相等 但是所引用的位址不是一樣的。為什麼呢?
首先虛拟機在編譯的過程中會把代碼優化一遍,也就是說上面的代碼可能不是我們想要的。先看一下編譯之後的代碼什麼樣子。
(class檔案反編譯之後的代碼)
Integer a5 = Integer.valueOf(128);
Integer a6 = Integer.valueOf(128);
Integer a7 = Integer.valueOf(127);
Integer a8 = Integer.valueOf(127);
Integer a9 = new Integer(127);
System.out.println(a5 == a6);
System.out.println(a7 == a8);
System.out.println(a9 == a8);
System.out.println(a9.equals(a8));
大家可以看到 編譯器優化之後真正運作的代碼是這樣子的。=128 優化成了 Integer.valueOf(128).
然而 Integer.valueOf做了什麼事情呢?怎麼會 兩個128相比較會是不同的對象 兩個127 相比較就是相同的資料呢?
帶着疑問翻開了jdk源碼(大家可以用 intellij idea 直接檢視源碼)
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);
}
首先第一眼看過去這是個靜态的方法,通過Interger對象可以直接調用。看裡面的内容,第一次看的時候猜想了作者的意思,大約是判斷傳送過來的i的資料 是否在 IntegerCache.low 和 IntegerCache.high中間,如果在的話傳回一個IntegerCache.cache[i + (-IntegerCache.low)]。如果不在的話 new 一個對象。接着順藤摸瓜,看下上面這3個東西是什麼。
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() {}
}
研究了代碼發現,IntegerCache 是一個靜态的 私有的方法,裡面有很多的靜态對象,靜态是什麼?簡單的可以認為全局變量,誰都可以用,被緩存的資料。low 是 -128 high 預設是127 也可以配置,上面的意思是在程式啟動的時候,初始化一部分資料存在記憶體中,這些資料是什麼呢?
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
大家可以看到 這裡進行了一次for循環,裡面有個new 關鍵字(new 就是在堆中配置設定一塊記憶體),每次都建立一個對象,内 容是 low和high 中間的所有資料面也就是 (-128)到(127)中的資料,共255 Interger對象,建立了這些對象之後,吧他們的位址的引用存在了static final Integer cache[]; 中,這是一個資料,而且是靜态的存在了緩存中,且不可變。
好了明白這些資料之後 再回過頭來看下上面的代碼所表達的意思。
Integer.valueOf(i)中,判斷傳送過來的i 是否在 -128 和127 中間,如果在就傳回return IntegerCache.cache[i + (-IntegerCache.low)]; 不在就傳回 一個new 對象。
是以當
Integer.valueOf(128)的時候 比 127大 ,每次都是new 一個新的對象,
Integer.valueOf(127)的時候 等于127,就從緩存中拿出127的位址,不用建立一個對象了。
是以
System.out.println(a5==a6);//false
System.out.println(a7==a8);//true
每次new 的都是一個新的對象,不管緩存中是否存在,是以 System.out.println(a9==a8);//false
這是我看interger源碼中比較有感觸的地方,有不到和錯誤之處請說出來大家一起進步。
}