超類Object中有這個equals()方法,該方法主要用於比較兩個對象是否相等。該方法的源碼如下:
public boolean equals(Object obj) { return (this == obj); }
我們知道所有的對象都擁有標識(內存地址)和狀態(數據),同時“==”比較兩個對象的的內存地址,所以說使用Object的equals()方法是比較兩個對象的內存地址是否相等,即若object1.equals(object2)為true,則表示equals1和equals2實際上是引用同一個對象。雖然有時候Object的equals()方法可以滿足我們一些基本的要求,但是我們必須要清楚我們很大部分時間都是進行兩個對象的比較,這個時候Object的equals()方法就不可以了,實際上JDK中,String、Math等封裝類都對equals()方法進行了重寫。下面是String的equals()方法:
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; }
對於這個代碼段:if (v1[i++] != v2[j++])return false;我們可以非常清晰的看到String的equals()方法是進行內容比較,而不是引用比較。至於其他的封裝類都差不多。
首先籠統的來講 “java中equals()方法和“==”運算符” 都是比較的地址,那為什麼我們在使用中總會出現混淆的情況呢老是弄錯呢,這是因為“重寫equals()方法”和一些 “特殊情況”的存在。
有兩種用法說明:
(1)對於字符串變量來說,使用“==”和“equals()”方法比較字符串時,其比較方法不同。
“==”比較兩個變量本身的值,即兩個對象在內存中的首地址。
“equals()”比較字符串中所包含的內容是否相同。
比如:
String s1,s2,s3 = "abc", s4 ="abc" ;
s1 = new String("abc");
s2 = new String("abc");
那麼:
s1==s2 是 false //兩個變量的內存地址不一樣,也就是說它們指向的對象不 一樣,故不相等。
s1.equals(s2) 是 true //兩個變量的所包含的內容是abc,故相等。
注意(1):
如果: StringBuffer s1 = new StringBuffer("a");
StringBuffer s2 = new StringBuffer("a");
結果: s1.equals(s2) //是false
解釋:StringBuffer類中沒有重新定義equals這個方法,因此這個方法就來自Object類,而Object類中的equals方法是用來比較“地址”的,所以等於false.
注意(2):
對於s3和s4來說,有一點不一樣要引起注意,由於s3和s4是兩個字符串常量所生成的變量,其中所存放的內存地址是相等的,所以s3==s4是true(即使沒有s3=s4這樣一個賦值語句)
(2)對於非字符串變量來說,"=="和"equals"方法的作用是相同的都是用來比較其對象在堆內存的首地址,即用來比較兩個引用變量是否指向同一個對象。
比如:
class A
{
A obj1 = new A();
A obj2 = new A();
}
那麼:obj1==obj2是false
obj1.equals(obj2)是false
但是如加上這樣一句:obj1=obj2;
那麼 obj1==obj2 是true
obj1.equals(obj2) 是true
總之:equals方法對於字符串來說是比較內容的,而對於非字符串來說是比較其指向的對象是否相同的。
== 比較符也是比較指向的對象是否相同的也就是對象在對內存中的的首地址。
String類中重新定義了equals這個方法,而且比較的是值,而不是地址。所以是true。
注意:
public class TestEquals { public static void main(String[] args) { int a = 3; int b = 4; int c = 3; System.out.println(a == b);//結果是false System.out.println(a == c);//結果是true System.out.println(a.equals(c));//錯誤,編譯不能通過,equals方法 //不能運用與基本類型的比較 } }
public class TestEquals { public static void main(String[] args) { Integer n1 = new Integer(30); Integer n2 = new Integer(30); Integer n3 = new Integer(31); System.out.println(n1 == n2);//結果是false 兩個不同的Integer對象,故其地址不同, System.out.println(n1 == n3);//那麼不管是new Integer(30)還是new Integer(31) 結果都顯示false System.out.println(n1.equals(n2));//結果是true 根據jdk文檔中的說明,n1與n2指向的對象中的內容是相等的,都是30,故equals比較後結果是true System.out.println(n1.equals(n3));//結果是false 因對象內容不一樣,一個是30一個是31 } }
這是Integer的實例,如果是其他的比如Double、Character、Float等也一樣。