關於equals與==的比較
最近在學習中遇到一個問題,兩個值相同的Integer型值進行==和equals比較時,發現了其中一些詭異的地方,然後就學習了一下有關Integer自動拆裝箱和常量池的概念
先來一個demo說明詭異在何處:
package cn.java.test; public class demo { public static void main(String[] args) { System.out.println("先用Integer i = x的方式為Integer物件賦值"); Integer i1 = 127; Integer i2 = 127; System.out.println(i1==i2); System.out.println(i1.equals(i2)); Integer i3 = 128; Integer i4 = 128; System.out.println(i3==i4); System.out.println(i3.equals(i4)); System.out.println(); System.out.println(); System.out.println("再用Integer i = new Integer(x)的方式為Integer物件賦值"); Integer i5 = new Integer(127); Integer i6 = new Integer(127); System.out.println(i5==i6); System.out.println(i5.equals(i6)); Integer i7 = new Integer(128); Integer i8 = new Integer(128); System.out.println(i7==i8); System.out.println(i7.equals(i8)); } }
結果如下:
先用Integer i = x的方式為Integer物件賦值
true
true
false
true
再用Integer i = new Integer(x)的方式為Integer物件賦值
false
true
false
true
首先了解一下,==比較的是兩個物件的地址 ,而equals比較的是兩個物件的具體的數值的大小。所以也不難解釋此demo中的所有的物件的equals的比較都為true了。所以接下來我們思考這個“==”的問題
此時便引出了思考了:
為什麼用Integer i = x的方式為Integer物件賦值的時候,
為Integer賦值為127的兩個物件的時候,i1==i2;的結果為true,也就是說這兩個數值為127的物件的地址一樣,
為Integer賦值為128的兩個物件的時候,i3==i4的地址卻為false,也就是說這兩個數值為128物件的地址不一樣。
當用Integer i = new Integer(x)的方式為Integer物件賦值的時候,
當分別new兩個數值127的物件的時候,i5==i6的結果為false;也就是說這兩個數值為127的物件的地址不一樣,
當分別new兩個數值128的物件的時候,i7==i8的結果為false;也就是說這兩個數值為127的物件的地址不一樣,
最後探其究竟發現原因如下:
因為Integer的數值在-128~127之間時,即在int的範圍內,預設是按照基本型別int來存放的,即用的是原生資料型別int,仍舊存在堆疊中,會在記憶體裡供重用,也就是說這之間的Integer值進行==比較時只是進行int原生資料型別的數值比較。在java裡面,當類載入時就將-128 到 127 的Integer物件建立了,並儲存在cache陣列中,一旦程式用Integer i = x的方式為Integer物件賦值的時候
而如果超出了int的範圍,用Integer i = x的方式為Integer物件賦值的時候,就按照物件的方式來存放和比較了,虛擬機器會自動建立一個新的物件,賦值多少次就建立多少次,而每建立一個新的物件,其地址肯定不一樣,故超範圍的Integer物件的地址不一樣。
這也就解釋了上面的結果了。
再給大家拓展一下String型別的有關==和equals的比較:
package cn.java.test;
public class demo {
public static void main(String[] args) {
String s = "abc";
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s==s1); //結果為true
System.out.println(s.equals(s1)); //結果為true
System.out.println(s==s2); //結果為false
System.out.println(s.equals(s2)); //結果為true
}
}
解釋:
String s = "abc";
這裡的"abc"稱為字串常量,也是存在堆疊中的,s中存放的就是指向這個堆疊地址的引用,如果再定義一個
String s1 = "abc";
這時,s與s1存放的是同一個地址的引用,即s與s1指向的是同一個字串常量,
s == s1的值是true,
但是如果有
String s2 = new String("abc");
這時s == s2則為false,因為使用new之後,每次生成的物件都不是同一個,即使儲存的內容相同。
上面的s == s1,s == s2其實比較的都是地址,並不是裡面的內容。如果要比較內容,可以使用equals()方法。