Java 基礎 - 如何重寫equals()


ref:https://www.cnblogs.com/TinyWalker/p/4834685.html

--------------------

編寫equals方法的建議:

  1. 顯示參數命名為otherObject, 稍后轉化成other變量
    public boolean equals(Object otherObject)
  2. 檢測this和otherObject是否是同一個對象的引用,是,返回true;
    if(this==otherObject){
        return true;
    }
  3. 檢測otherObject是否為null, 是, 返回false;
    if(otherObject == null){
        return false;
    }
  4. 比較this和otherObject是否屬於同一個類. 如果equals的語義在每個子類中有所改變,就使用getClass檢測:
    if(getClass() != otherObject.getClass()){
        return false;
    }
    如果子類語義相同,使用instanceof檢測:
    if(!(otherObject instanceof Employee)){
        return false;
    }
  5. 將otherObject轉化為相對應的類型變量other
    Employee other = (Employee)otherObject;
  6. 對所需要的比較的數據域進行比較. 如果是基本數據類型,使用a==b比較; 如果是對象比較,調用Objects.equals(a, b)進行比較
    return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);

整個流程可以參照例1;

 

例1:雇員對象比較

如果兩個雇員對象的姓名, 薪水和雇佣一樣,就認為它們相等.重寫equals方法如下:

復制代碼
public class Employee {

    private String name;
    private double salary;
    private Date hireDay;

    ... 

    @Override
    public boolean equals(Object obj) {
        // 如果為同一對象的不同引用,則相同
        if (this == obj) {
            return true;
        }
        // 如果傳入的對象為空,則返回false
        if (obj == null) {
            return false;
        }

        // 如果兩者屬於不同的類型,不能相等
        if (getClass() != obj.getClass()) {
            return false;
        }

        // 類型相同, 比較內容是否相同
        Employee other = (Employee) obj;

        return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
    }

 

 

復制代碼

  注意,比較通過Objects中靜態函數equals比較兩個對象是否相等.該方法源碼如下:

 public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

 這樣,當兩個對象都為null時,返回true,例如,兩個Employee對象的name都為null, 返回true; 如果第一個對象不為null,則調用a.equals(Object obj)方法

 

常見equals方法實現錯誤

1-未使用@override對覆蓋超類的方法進行標記.

復制代碼
public class Employee {
    public boolean equals(Employee other) {


    return Objects.equals(name, other.name) && salary ==other.salary && Objects.equals(hireDay, other.hireDay);
}
復制代碼

 

這個方法聲明的顯示參數類型是Employee. 其結果並沒有覆蓋Object中的equals方法,而是定義了一個完全無關的方法.為了避免發生類型錯誤,可以使用@override對覆蓋超類的方法進行標記.

 

2-沒有同時override hashcode()函數 

object對象中的 public boolean equals(Object obj),對於任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象時,此方法才返回 true;
注意:當此方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定聲明相等對象必須具有相等的哈希碼。如下:
(1)當obj1.equals(obj2)為true時,obj1.hashCode() == obj2.hashCode()必須為true
(2)當obj1.hashCode() == obj2.hashCode()為false時,obj1.equals(obj2)必須為false
如果不重寫equals,那么比較的將是對象的引用是否指向同一塊內存地址,重寫之后目的是為了比較兩個對象的value值是否相等。特別指出利用equals比較八大包裝對象
(如int,float等)和String類(因為該類已重寫了equals和hashcode方法)對象時,默認比較的是值,在比較其它自定義對象時都是比較的引用地址
hashcode是用於散列數據的快速存取,如利用HashSet/HashMap/Hashtable類來存儲數據時,都是根據存儲對象的hashcode值來進行判斷是否相同的。
這樣如果我們對一個對象重寫了euqals,意思是只要對象的成員變量值都相等那么euqals就等於true,但不重寫hashcode,那么我們再new一個新的對象,
當原對象.equals(新對象)等於true時,兩者的hashcode卻是不一樣的,由此將產生了理解的不一致,如在存儲散列集合時(如Set類),將會存儲了兩個值一樣的對象,
導致混淆,因此,就也需要重寫hashcode()
舉例說明:


        public override bool Equals(object obj) { if (!(obj is BalanceSheetReport expect)) return false; return this.EndSum == expect.EndSum && this.PreSum == expect.PreSum && this.SequenceId == expect.SequenceId && this.ProjectId == expect.ProjectId; } public override int GetHashCode() { return this.PreSum.GetHashCode() ^ this.EndSum.GetHashCode() ^ this.SequenceId.GetHashCode() ^ this.ProjectId.GetHashCode(); }
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM