簡體   English   中英

覆蓋equals方法

[英]Override the equals method

我目前正在為考試做准備。 在過去的論文中,有一個問題,

重寫以下類中的equals方法。 該方法應檢查整個狀態的內容是否相等。

 class Employee
    {
        String firstName;
        int age;
    } 

[2分]

我做了一些擺弄正確答案的擺弄,到目前為止已經提出了這個建議。 有沒有更簡單的方法來回答這個問題,對嗎? 非常感謝您的幫助。

 public class Employee
    {

     int age;

    public boolean equals(Object obj)
    {
        if(this == obj)
            {
                return true; //Reference equality.
            }    
        if(!(obj instanceof Employee)) 
            {
                return false; // not the same type.
            }
        Employee other = (Employee) obj;
        return firstName == other.firstName;
        return age == other.age;
        }
    }

要點:

  1. 您需要檢查obj是否為null
  2. 要比較Java中的String內容,請使用equals() ,即firstName.equals(other.firstName) 首先檢查firstName是否為null

這是一個改進的實現:

public boolean equals(Object obj)
{
  if(obj == null)
  {
    return false;
  }
  if(this == obj)
  {
    return true; //Reference equality.
  }    
  if(this.getClass() != obj.getClass())
  {
    return false;
  }
  Employee other = (Employee) obj;
  if(firstName == null)
  {
    if(other.firstName != null)
    {
      return false;
    }
  }
  else if(!firstName.equals(other.firstName))
  {
    return false;
  }
  return age == other.age;
}

編輯 :更新了類型比較,以根據@Mark Peters的答案使equals()對稱。

采用

return (((this.firstName == null || other.firstName == null)
            && this.firstName == other.firstName)
       ||
       this.firstName.equals(other.firstName))
       && age == other.age;

這也處理null情況。

字符串firstName應該與.equals()進行比較,而不是==。 對於原始int age字段,==比較可以。

如果兩個名字相同但年齡不相等怎么辦? 這不應該失敗嗎?

類似於return (firstName.equals(obj.firstName)) && (age == obj.age);

當然,如果this.firstName為null,則不會考慮這種情況,這將導致拋出NullPointerException

如果雇員的名字都為空,是否認為雇員平等? 如果一個為空而另一個不為空怎么辦? 假設兩者都必須為null,或者兩者都必須為String.equals(),則可以使用:

return ((null == firstName && null == obj.firstName) 
  || (null != firstName && firstName.equals(obj.firstName)))
  && (age == obj.age);

而不是您的2個return語句。 其余的看起來還可以。

需要注意的一件事,我不會想象您會在考試中陷入困境……

當類不是最終的時,執行instanceof通常是不佳的做法。 這是因為equals()必須對稱。 接受子類(它們也可能使用其自己的新方面實現equals)可能導致其不對稱。

示例(我認為該示例與Effective Java 2ed中使用的示例相同):

class Point {
    protected int x, y;
    //equals method uses instanceof Point and checks x and y values are the same
}

class ColorPoint extends Point {
    protected Color color;
    //equals method checks that it's a ColorPoint, that super.equals is true, 
    //then checks the Color
}

new Point(1, 2).equals(new ColorPoint(1, 2, Color.red)); //true
new ColorPoint(1, 2, Color.red).equals(new Point(1, 2)); //false

這是非常微妙的一點,即使這里的大多數答題者也沒有考慮到。 但這是大多數equals生成器(例如您最喜歡的IDE中的生成器)傾向於進行精確的類比較的原因:

  if ( this.getClass() != other.getClass() ) {
     return false;
  }

當equals方法使用instanceof時,通常最好記錄子類必須遵循完全相同的規范。

您的最后一行(年齡比較)無法訪問; 您不應該使用==比較字符串; 並且您需要考慮空值。

由於一般的運動似乎是為您全力以赴,因此這里是Eclipse的實現:

public class Employee {
    private final String firstName;
    private final int age;

    public Employee(final String firstName, final int age) {
        super();
        this.firstName = firstName;
        this.age = age;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Employee other = (Employee) obj;
        if (age != other.age) {
            return false;
        }
        if (firstName == null) {
            if (other.firstName != null) {
                return false;
            }
        } else if (!firstName.equals(other.firstName)) {
            return false;
        }
        return true;
    }
}

並進行一系列測試:

import org.junit.Test;

public class EmployeeTest {
    @Test
    public void testEmployeeEquals() {
        final Employee nullNameEmp = new Employee(null, -1);
        final Employee empA1 = new Employee("a", 1);
        final Employee empA1Clone = new Employee("a", 1);
        final Employee empA2 = new Employee("a", 2);
        final Employee empB1 = new Employee("b", 1);
        final Employee empB2 = new Employee("b", 2);
        final Employee subEmp = new Employee("a", 1) {

        };

        assert !nullNameEmp.equals(empA1);
        assert !nullNameEmp.equals(empA1Clone);
        assert !nullNameEmp.equals(empA2);
        assert !nullNameEmp.equals(empB1);
        assert !nullNameEmp.equals(empB2);
        assert !nullNameEmp.equals(subEmp);
        assert !nullNameEmp.equals(null);

        assert !empA1.equals(nullNameEmp);
        assert empA1.equals(empA1Clone);
        assert !empA1.equals(empA2);
        assert !empA1.equals(empB1);
        assert !empA1.equals(empB2);
        assert !empA1.equals(subEmp);
        assert !empA1.equals(null);

        assert !empA2.equals(nullNameEmp);
        assert !empA2.equals(empA1);
        assert !nullNameEmp.equals(empA1Clone);
        assert !empA2.equals(empB1);
        assert !empA2.equals(empB2);
        assert !empA2.equals(subEmp);
        assert !empA2.equals(null);

        assert !empB1.equals(nullNameEmp);
        assert !empB1.equals(empA1);
        assert !empB1.equals(empA1Clone);
        assert !empB1.equals(empA2);
        assert !empB1.equals(empB2);
        assert !empB1.equals(subEmp);
        assert !empB1.equals(null);

        assert !empB2.equals(nullNameEmp);
        assert !empB2.equals(empA1);
        assert !empB2.equals(empA1Clone);
        assert !empB2.equals(empA2);
        assert !empB2.equals(empB1);
        assert !empB2.equals(subEmp);
        assert !empB2.equals(null);

        assert !subEmp.equals(nullNameEmp);
        assert !subEmp.equals(empA1);
        assert !subEmp.equals(empA1Clone);
        assert !subEmp.equals(empA2);
        assert !subEmp.equals(empB1);
        assert !subEmp.equals(empB2);
        assert !subEmp.equals(null);

        assert nullNameEmp.equals(nullNameEmp);
        assert empA1.equals(empA1);
        assert empA1Clone.equals(empA1Clone);
        assert empA2.equals(empA2);
        assert empB1.equals(empB1);
        assert empB2.equals(empB2);
        assert subEmp.equals(subEmp);
    }
}
public boolean equals(Object o){
   if(this==o){ //same instance, no need to check more
       return true;
   }
   if(o instanceof Employee){ //when null this will yield false
       Employee other = (Employee) o;
       return (this.name == other.name || (this.name != null && this.name.equals(other.name)) && this.age == other.age;
   }
   return false;
}

將所有已經提到的部分歸納為一個答案:

public boolean equals(Object obj) {
    if(this == obj) {
        return true; //Reference equality.
    }
    if(obj == null || !(obj instanceof Employee))
    {
        return false; // not the same type.
    }
Employee other = (Employee) obj;
return (firstName.equals(other.firstName) && age == other.age);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM