前言
覆盖equals方法看起来似乎很简单,但是有许多覆盖方式会导致错误,并且后果非常严重,最容易避免这类问题的办法就是不覆盖equals方法。
什么时候需要覆盖equals方法?如果类具有自己特有的“逻辑相等”概念(不同于对象等同),而且超类还没有覆盖equals方法以实现期望的行为,这时需要覆盖equals方法。
覆盖equals
覆盖equals方法时,必须遵守它的通用约定,如果你违反了它们,就会发现你的程序将表现不正常,甚至奔溃,而且很难找到失败的根源。
通用约定
自反性。对于任何非null的引用值x、x,equals(x)必须返回true。
对称性。对于任何非null的引用值x、y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
传递性。对于任何非null的引用值x、y、z,如果x.equals(y)返回true,并且y.equals(z)返回true,则x.equals(z)必须返回true。
一致性。对于任何非null的引用值x、y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致地返回false。
非空性。对于任何非null的引用值x、x,equals(null),必须返回false。
一般IDE工具,如IntelliJ IDEA可以帮助实现equals方法覆盖。基本上是符合以上约定的。
实现高质量equals方法的诀窍
使用==操作符检查“参数是否为这个对象的引用”。
使用instanceof操作符检查“参数是否为正确的类型”。
把参数转化为正确的类型。
对于该类的中每个关键域,检查参数中的域是否与该对象中对应的域想匹配。
示例
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (this==obj) return true;
if (!(obj instanceof Point)) {