先看一段代碼:
String test1 = "add";String test2 = "add";String test3 = new String("add");String test4 = new String("add");System.out.println(test1 == test2);System.out.println(test1.equals(test2));System.out.println(test3 == test4);System.out.println(test3.equals(test4));System.out.println(test1 == test3);System.out.println(test1.equals(test4));
運行結果:
truetruefalsetruefalsetrue
分析:
結合上面的語句,我簡單說一下字串的賦值過程。當電腦執行Stringtest1 = "add"的時候,它會先檢查記憶體中是否存在存有“add”的地址空間,如果存在,直接將變數test1指向該地址空間。如果不存在,就建立一塊地址空間存放“add”,然後將變數test1指向該地址空間。所以,test1和test2實際上指向的是同一地址空間。當電腦執行Stringtest3 = new String("add")時,它會直接在記憶體中開闢一塊地址空間存放“add”,然後將變數test3指向該地址空間。所以最終的記憶體分布如所示:
結論:
從程式的運行結果和來看,我們可以得出:“==”比較的是兩個變數的存放地址,只要地址不一樣,那它們就是不相等。而“equals”要求的條件就沒有那麼苛刻,只要值相等了,那它就是true。
繼續深入:
讓我們來看看對象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;}
從源碼中我們可以看到,String類重寫了Object類的equals方法,它同樣使用“==”進行記憶體位址的比較,但是String類對比較進行了擴充,使之出現與“==”不同的結果。
擴充:
“==”是基類Object的equal實現,不同的類對它進行了不同的重寫,進而導致比較的不同。所以,你完全可以建立一個類,然後重寫基類的equals方法,讓它按照你自己的方式進行比較。當然,重寫equals方法的情況較少,可能我們更多用到的是重寫toString方法,但是,他們的原理是一樣的。