乐者为王

Do one thing, and do it well.

如何编写完美的equals方法

Java语言规范要求equals方法具有下面的特点:

  1. 自反性(reflexive):对于任意非空引用x,x.equals(x)应返回true;
  2. 对称性(symmetric):对于任意引用x、y,当且仅当y.equals(x)返回true时,x.equals(y)返回true;
  3. 传递性(transitive):对于任意引用x、y、z,如果x.equals(y)返回true,且y.equals(z)也返回true,那么x.equals(z)应返回true;
  4. 一致性(consistent):如果x和y引用的对象没有改变,那么对x.equals(y)的重复调用应返回同一结果;
  5. 对任意非空引用x,x.equals(null)应返回false。

下面是编写完美equals方法的建议:

1
2
3
4
5
6
7
8
9
10
11
// 测试this和other是否是同一个对象
if (this == other) return true;
// 测试other是否为null,如果是就返回false
if (other == null) return false;
// 测试this和other是否属于同一个类
if (getClass() != other.getClass()) {
    return false;
}
// 将other对象的类型转换为你的类所属的类型
ClassName obj = (ClassName)other;
// 最后测试需要比较的字段。使用==比较基本类型字段,使用equals比较对象类型字段

如果遵循以上的规则定义了一个类的equals方法,定义其子类的equals方法时,首先调用父类的equals方法,如果这项测试能通过,那么再比较子类的字段。

1
if (!super.equals(other)) return false;

这里有个问题是如果this和other两个对象不是同一个类,equals方法该如何工作?有些程序员可能会使用instanceof代替getClass()来做判断,但这种方法是错误的,因为它违反了规则2所要求的对称性。

Comments