繁体   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