Contents
  1. 1. equals方法
    1. 1.1. 引用同一
    2. 1.2. 状态相等

Object类是Java中的一个全局超类——每一个Java类都扩展了它。但是你不必显示地如下声明:

1
public class Employee extends Object

equals方法

引用同一

equals方法是Object类中用于判断一个对象和另一个对象是否相等的方法。在Object类中的实现如下:

1
2
3
public boolean equals(Object obj) {
return (this == obj);
}

从源代码可知,该实现是检查两个对象的引用是否相等,也即是检查两个对象是否指向Java堆中的同一个对象。这是因为,如果两个对象的引用指向同一个Java堆中的对象,则这两个对象必然是相等的。对极少数类的
对象来说,这个实现已经足够了。例如两个PrintStream对象。

状态相等

如上文所述,对大多数类来说,Object中的equals实现是不够用的。因为很多时候,我们认为两个对象相等是基于它们具有相同的状态(即对象的属性,field)。例如,两个Employee对象,如果它们具有相同的姓名(name),
工资(salary)和雇佣日期(hire day),那它们就是相等的。它的实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Employee {
...
public boolean equals(Object otherObject) {
if (this == otherObject)
return true;
if (otherObject == null)
return false;
if (getClass() != otherObject.getClass())
return false;
Employee other = (Employee) otherObject;
return name.equals(other.name)
&& salary == other.salary;
&& hireDay.equals(other.hireDay);
}
}

上面的代码中,首先判断两个对象是否同一,其次判断被比较对象是否为null,再次比较两个对象所属的类是否相同(在此处,假定必须类相同才有可能相等),最后比较各个状态是否相等。注意如果状态也是对象的话,
则会递归调用它们的equals方法。

这里要注意的是,Employee对象的name和hireDay等状态是有可能为null的,为了确保在这种情况下程序也是正确的,可以使用Objects.equals方法。调用Objects.equals(a, b),若两个参数都是null返回true,
若其中一个为null返回false,以上都不成立则调用a.equals(b)。因此,上面方法的最后一条语句可修改为

1
2
3
return Objects.equals(name, other.name)
&& salary == other.salary;
&& Objects.equals(hireDay, other.hireDay);

当在扩展类中定义了equals方法时,须首先调用超类的equals方法,如果返回false,则两个对象不可能相等。若返回true,即是超类定义的状态相等。则继续比较子类定义的状态。

Contents
  1. 1. equals方法
    1. 1.1. 引用同一
    2. 1.2. 状态相等