[英]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;
}
}
要点:
obj
是否为null
。 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.