java中有兩種類型
- 基本類型
基本數據類類型存的是數值本身
- 引用類型
引用類型變量在內存放的是數據的引用
基本類型通過==比較的是他們的值大小,而引用類型比較的是他們的引用地址
正文
在一些特殊的類中,如Integer在使用==比較的時候往往非常容易出錯,下面通過幾個例子來探索一下具體的原理
代碼片段
public class Test03 { public static void main(String[] args) { Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System. out.println( f1 == f2); //true System. out.println( f3 == f4); //false }}
當我們給一個Integer賦予一個int類型的時候會調用Integer的靜態方法valueOf。
Integer f1 = Integer.valueOf(100);
Integer f2 = Integer.valueOf(100);
Integer f3 = Integer.valueOf(150);
Integer f4 = Integer.valueOf(150);
思考:那么Integer.valueOf()返回的Integer是不是是重新new Integer(num);來創建的呢?如果是這樣的話,那么== 比較返回都是false,因為他們引用的堆地址不一樣。
具體來看看Integer.valueOf的源碼
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}
在IntegerCache中cache數組初始化如下,存入了-128 - 127的值
cache = new Integer[(high - low) + 1];int j = low;for( int k = 0; k < cache.length ; k ++) cache[k] = new Integer(j ++);
從上面我們可以知道給Interger 賦予的int數值在-128 - 127的時候,直接從cache中獲取,這些cache引用對Integer對象地址是不變的,但是不在這個范圍內的數字,則new Integer(i) 這個地址是新的地址,不可能一樣的
代碼片段
public static void main(String[] args) { Integer a = new Integer(3); Integer b = 3; int c = 3; System.out.println(a == b); System.out.println(a == c); }
a == b分析
Integer b = 3; 自動調用Integer.valueOf(3) 返回一個Integer的對象。 這個對象存放到cache中的(上面一段代碼分析)。 而 Integer a = new Integer(3);這里創建了一個新的對象Integer 所以 a == b 返回的是false
a == c 分析
一個Integer 與 int比較,先將Integer轉換成int類型,再做值比較,所以返回的是true。
參考資料:《探索java基本類型和包裝類型的使用運算符==進行比較的底層細節》
延伸
java中還有與Integer類似的是Long,它也有一個緩存,在區間[-128,127]范圍內獲取緩存的值,而Long與long比較的時候先轉換成long類型再做值的比較
Double類型,它沒有緩存,但是當Double與double比較的時候會先轉換成double類型,再做值的比較
一道牛客網的習題 
分析:
A: Integer 與 int 比較的時候將Integer轉成int在比價兩個值大小,所以排除
B: Integer i01 = 59;默認處理Integer i01 =Integer.valueOf(59); i01與 i03數值在-128 - 127之間,所以在cache緩存中獲取Integer對象,他們引用地址是一樣的。所以排除
C: i03獲取的是cache中緩存好的的Integer地址,而i04是重新在堆中創建一個地址,所以兩個地址是不一樣的
D:A一樣的原理。
