首先我們先看三個實例結果:
實例1:
String s1 = new String("abc");
String s2 = new String("abc");
s1==s2——結果爲false;
s1.equals(s2)——結果爲true;
實例2:
Object obj1 = new Object();
Object obj2 = new Object();
obj1==obj2;
obj1.equals(obj2);
結果都爲false;
示例3:
Object obj1 = new Object();
Object obj2 = obj1;
obj1==obj2;
obj1.equals(obj2);
結果都爲true;
看到這三種結果,雖然大家都知道這個結果,初學者可能難免都會產生一種說不清道不明感覺,下面是個人對==和equals兩種比較操作的理解,不對之處也請各們高手指正,以免我誤道初學者。
首先我來解說示例1:
先讓我們來看看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;
}
如上代碼所示,equals方法的第一步就是進行==比較,而我們知道,兩個String類型的==比較結果是false,所以我們繼續往下看代碼,當==結果爲false時,並且比較類型爲String時,就會把兩個String轉化爲char數組,通過比較char數組中的每個值來判斷最終結果。
再先我來解說示例2:
還是讓我們先看一段Object類equals方法的源碼:
public boolean equals(Object obj) {
return (this == obj);
}
代碼所示,當兩個對象類型進行equals方法比較時,默認是進行==比較
這時大家可能會迷糊了,心裏就會想:
Object obj1 = new Object();
Object obj2 = new Object();
如果obj1與obj2兩個對象中的值完全一樣,爲什麼他們的==和equals都會返回false呢?想不通,不急,不妨看看我說的對不對創建一個對象類型,如Object obj = new Object();在JVM中會開闢兩塊內存,一塊爲obj,在這我稱之爲變量內存(存儲在棧中),一塊爲new Object();在這裏我稱之爲對象內存(存儲在堆中);而變量僅僅只是對象的一個引用而已。
在上面的示例中我們創建了obj1與obj2兩個變量,分別在JVM中開闢了兩塊內存,同時並具有唯一內存地址,而當對象類型使用==進行比較時,恰恰就是比較的這兩個對象的內存地址值(內存地址的其中一種表示形式就是hashcode值),所以對象類型的==結果爲false。又因爲Object的equals默認就是進行==比較,所以對象類型的equals返回結果也是false;
有了示例2的解說,相信大家對示例3的結果應該會比較清楚了,因爲obj2=obj1,意味着new Object()不僅被obj1變量引用,同時還被obj2變量引用,所以,這兩個變量指向同一塊內存對象,所以他們的==和equals都爲true。
簡言之:
當比較的雙方爲基本數據類型時,==比較的是雙方的值。
當比較的雙方爲對象數據類型時,==和equals都比較的是雙方的變量所指向對象(值)的內存地址。
而通過示例1我們可以得出,引用類型的equals比較的是兩個對象的內容是否相等。
所以我們在判斷兩個對象是否相等時,需要重寫equals方法逐個判斷對象中的內容是否相等。
所以使用使用對象clone出來的對象,雙方==和equals也還是false,因爲當我們clone對象時,仍然是返回一個new Object(),源Object與clone出的Object具有不相同的內存地址。