今天在做實驗的時候,發現了一個比較奇怪的問題:兩個Integer型變量用==進行比較時,有時候能成功有時候不能成功。舉個例子:
代碼1:
Integer l1 = 122; Integer l2 = 122; if(l1 == l2) System.out.println("Right"); else System.out.println("Wrong");
運行這段代碼時,程序會輸出:Right。對於另一個例子:
代碼2:
Integer l1 = 233; Integer l2 = 233; if(l1 == l2) System.out.println("Right"); else System.out.println("Wrong");
運行這段代碼時,程序會輸出Wrong。但當對代碼2進行修改時:
代碼3:
Integer l1 = 233; int l2 = 233; if(l1 == l2) System.out.println("Right"); else System.out.println("Wrong");
在運行這段代碼時,程序會輸出Right。如果換一種定義方式時:
代碼4:
Integer l1 = 233; Integer l2 = new Integer(233); if(l1 == l2) System.out.println("Right"); else System.out.println("Wrong");
運行這段代碼時,程序會輸出Wrong。
關於這種現象,查了下資料,總結如下:
1.實際上Java中定義的Integer變量會通過Integer.valueOf()方法生成一個實例,即:
Integer l1 = 122 會被編譯成 Integer l1 = Integer.valueOf(122),而關於valueOf()方法的源碼:
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); }
看一下源碼就會明白,對於-128到127之間的數,會進行緩存,Integer l1 = 122時,會將122進行緩存,下次再寫Integer l2 = 122時,就會直接從緩存中取,就不會new了,相當於生成的為同一個對象,。所以代碼1的運行結果是Right。
而對於這個范圍之外的數值,valueOf()相會重新new一個對象,所以就不相等了,所以代碼2的裕興結果就是Wrong。
2.對於代碼3,Integer型變量與int型變量進行比較時,實質上是把Integer類型變量拆箱成int類型,然后進行比較,相等則返回true,否則返回false。此處的拆箱調用的是intValue()方法。所以代碼3的運行結果是Right。
3.對於代碼4,就比較好解釋了,因為new相當於重新定義了一個新的對象,即l1的引用實質是指向在堆中了,而l2實質是指向在常量池中了(關於變量在內存中的位置可參考:http://www.cnblogs.com/wangkundentisy/p/6636340.html),所以兩者是不可能相等的,故輸出結果就是Wrong。
4.總之,要想比較兩個Intger型變量的值最好用Integer.intValue()方法生成int型后再比較。
5.Integer型變量與int型變量之間可以直接比較,此時自動進行拆箱操作。
參考:
1.https://www.cnblogs.com/liuling/archive/2013/05/05/intAndInteger.html
2.http://blog.csdn.net/snail_rao/article/details/7639194
3.《JAVA核心技術》