超類Object中有這個equals()方法,該方法主要用于比較兩個對象是否相等。該方法的源碼如下:
[java] view plain copy我們知道所有的對象都擁有標識(內存地址)和狀態(數據),同時“==”比較兩個對象的的內存地址,所以說使用Object的equals()方法是比較兩個對象的內存地址是否相等,即若object1.equals(object2)為true,則表示equals1和equals2實際上是引用同一個對象。雖然有時候Object的equals()方法可以滿足我們一些基本的要求,但是我們必須要清楚我們很大部分時間都是進行兩個對象的比較,這個時候Object的equals()方法就不可以了,實際上JDk中,String、Math等封裝類都對equals()方法進行了重寫。下面是String的equals()方法:
[java] view%20plain copy對于這個代碼段:if%20(v1[i++]%20!=%20v2[j++])return%20false;我們可以非常清晰的看到String的equals()方法是進行內容比較,而不是引用比較。至于其他的封裝類都差不多。
在Java規范中,它對equals()方法的使用必須要遵循如下幾個規則:
equals%20方法在非空對象引用上實現相等關系:
1、自反性:對于任何非空引用值%20x,x.equals(x)%20都應返回%20true。
2、對稱性:對于任何非空引用值%20x%20和%20y,當且僅當%20y.equals(x)%20返回%20true%20時,x.equals(y)%20才應返回%20true。
3、傳遞性:對于任何非空引用值%20x、y%20和%20z,如果%20x.equals(y)%20返回%20true,并且%20y.equals(z)%20返回%20true,那么%20x.equals(z)%20應返回%20true。
4、一致性:對于任何非空引用值%20x%20和%20y,多次調用%20x.equals(y)%20始終返回%20true%20或始終返回%20false,前提是對象上%20equals%20比較中所用的信息沒有被修改。
5、 對于任何非空引用值%20x,x.equals(null)%20都應返回%20false。
對于上面幾個規則,我們在使用的過程中最好遵守,否則會出現意想不到的錯誤。
在java中進行比較,我們需要根據比較的類型來選擇合適的比較方式:
1) 對象域,使用equals方法%20。 2) 類型安全的枚舉,使用equals或==%20。 3) 可能為null的對象域%20:%20使用%20==%20和%20equals%20。 4) 數組域%20:%20使用%20Arrays.equals%20。 5) 除float和double外的原始數據類型%20:%20使用%20==%20。 6) float類型:%20使用Float.foatToIntBits轉換成int類型,然后使用==。 7) double類型:%20使用Double.doubleToLongBit轉換成long類型,然后使用==。
至于6)、7)為什么需要進行轉換,我們可以參考他們相應封裝類的equals()方法,下面的是Float類的:
[java] view%20plain copy原因嘛,里面提到了兩點:
[java] view%20plain copy子類:Employee
[java] view%20plain copy上面父類Person和子類Employee都重寫了equals(),不過Employee比父類多了一個id屬性。測試程序如下:
[java] view%20plain copy上面定義了兩個員工和一個普通人,雖然他們同名,但是他們肯定不是同一人,所以按理來說輸出結果應該全部都是false,但是事與愿違,結果是:true、true、false。
對于那e1!=e2我們非常容易理解,因為他們不僅需要比較name,還需要比較id。但是p1即等于e1也等于e2,這是非常奇怪的,因為e1、e2明明是兩個不同的類,但為什么會出現這個情況?首先p1.equals(e1),是調用p1的equals方法,該方法使用instanceof關鍵字來檢查e1是否為Person類,這里我們再看看instanceof:判斷其左邊對象是否為其右邊類的實例,也可以用來判斷繼承中的子類的實例是否為父類的實現。他們兩者存在繼承關系,肯定會返回true了,而兩者name又相同,所以結果肯定是true。
所以出現上面的情況就是使用了關鍵字instanceof,這是非常容易“專空子”的。故在覆寫equals時推薦使用getClass進行類型判斷。而不是使用instanceof。
新聞熱點
疑難解答