equals()方式是顶级父类Object中的方法,自定义类若想重新写equals()方法,则需要考虑以下几个特性
- 自反性:对于任何非null的引用值,x.equals(x)必须返回true
- 对称性:对于任何非null的引用值x和y,当且仅当y.euqals(x)返回true时,x.equals(y)必须返回true
- 传递性:对于任何非null的引用值x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)也必须返回true
- 一致性:多次调用equals方法结果不变
- 对于任何非null的引用值,x.equals(null)必须返回false
结合所有这些要求,得出一下实现高质量equals方法的诀窍
- 使用==操作符检查"参数是否为这个对象的引用"
- 使用instranceof操作符检查"参数是否为正确的类型"
- 把参数转化成正确的类型
- 对于该类中的每个"关键域",检查关键域是否与该对象中对应的域相匹配
例子:
public final class PhoneNumber {
private final short areaCode;
private final short prefix;
private final short lineNum;
public PhoneNumber(short areaCode, short prefix, short lineNum) {
this.areaCode = areaCode;
this.prefix = prefix;
this.lineNum = lineNum;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PhoneNumber that = (PhoneNumber) o;
return areaCode == that.areaCode && prefix == that.prefix && lineNum == that.lineNum;
}
@Override
public int hashCode() {
return Objects.hash(areaCode, prefix, lineNum);
}
下面是最后的一些告诫
- 覆盖equals总要覆盖hashCode
- 不要企图让equals方法过于智能
- 不要将equals声明中的Object替代那个替换为其他的类型