之前一直看資料有寫,當一個int類型的數據<128時,用==比較是相等的,但是當>128時,比較就不相等了。
<span style="font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:KaiTi_GB2312;">public class Test {
public static void main(String[]args ){
int i = 128;
Integer i2 = 128;
Integer i3 = new Integer(128);
//Integer會自動拆箱爲int,所以爲true
System.out.println(i == i2);//true
System.out.println(i == i3);//true
System.out.println(i2 == i3);//false 堆對象和棧對象,對象之間比較,而自動拆箱後對象都轉換爲int比較值
System.out.println("----------------------");
Integer i5 = 127;//java在編譯的時候,被翻譯成-> Integer i5 = Integer.valueOf(127);
Integer i6 = 127;
System.out.println(i5 == i6);//true
// Integer i51 = 128;
// Integer i61 = 128;
// System.out.println(i51 == i61);//false
Integer i52=new Integer(126);
Integer i62=new Integer(126);
System.out.println(i52==i62);//false 堆中兩個不同對象
System.out.println("----------------------");
Integer ii5 = new Integer(127);
System.out.println(i5 == ii5); //false 堆對象和棧對象,對象之間比較,
Integer i7 = new Integer(128);
Integer i8 = new Integer(128);
System.out.println(i7 == i8); //false <span style="line-height: 21.6px; font-family: tahoma, arial, sans-serif;">堆中兩個不同對象</span>
}
}</span></span></span>
上面是一個例子,大家可以自己運行一下。之前一直不理解爲什麼?今天看了源碼才清楚。
下面把源碼貼出來,大家感受一下,@@@@@
<span style="font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-family:KaiTi_GB2312;font-size:14px;">private static class IntegerCache {
//這是默認的最小值,這個不可以改變
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// 源碼中寫這個是一個可以手動設置的值,但是默認是127
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++);
}</span></span></span>
我們可以看到,integer的自動緩存池的大小是 [-128 127] 這也是爲什麼就我們的環境運行出來,大於127就不再相等。
通過屬性去取的high的值,sun.misc.VM.getSavedProperty,
這個屬性是在使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN參數即可將Integer的自動緩存區間設置爲[-128,NNN]。注意區間的下界固定在-128不可配置。
在client模式下該參數無效。這個參數是server模式專有的,在c2_globals.hpp中聲明,默認值是128;不過這個默認值在默認條件下不起作用,要手動設置它的值或者是開啓-XX:+AggressiveOpts參數才起作用。
那麼在這裏緩存池到底起到什麼作用?
Integer i5 = 127時,會將127進行緩存,下次再寫Integer i6 = 127時,就會直接從緩存中取,就不會new了。所以22行的結果爲true,而25行爲false。(自動裝箱時纔會發生,Integer a=value,這種棧對象形式(類似 string str="abc"),如果Integer b= new Integer(value),則不會,分別在堆中建立對象)
對於23行和26行,因爲對象不一樣,所以爲false。
對於以上的情況總結如下:
①無論如何,Integer與new Integer不會相等(棧對象,堆對象)。不會經歷拆箱過程,i3的引用指向堆,而i4指向專門存放他的內存(常量池),他們的內存地址不一樣,所以爲false。
②兩個都是非new出來的Integer(兩個棧對象,涉及自動裝箱),如果數在-128到127之間,則是true,否則爲false
java在編譯Integer i2 = 128的時候,被翻譯成-> Integer i2 = Integer.valueOf(128);而valueOf()函數會對-128到127之間的數進行緩存。
③兩個都是new出來的,都爲false(兩個堆對象)。
④int和integer(無論new否)比(Integer涉及自動拆箱),都爲true,因爲會把Integer自動拆箱爲int再去比。