一 点睛
如果我们用相同类型的两个引用变量a和b进行等价性测试(a==b),我们检测的是它们的标识是否相同,即引用是否相同。一般我们希望能够检查数据类型的值(对象状态)是否相同或者实现针对该类型的规则。
Java为我们开了个头,为Integer、Double和String等标准数据类型以及一些File和URL的复杂数据类型提供了实现。在处理这些数据时,可以使用内置的equals实现。
Java约定equals必须是一种等价性关系。它必须具有如下性质:
1 自反性:x.equals(x)为true。
2 对称性:当且仅当y.equals(x)为true时,x.equals(y)返回true。
3 传递性:如果x.equals(y)和y.equals(z)均为true,x.equals(z)也将为true。
4 一致性:当两个对象均未被修改时,反复调用x.equals(y)总是会返回相同的值。
5 非空性:x.equals(null)总是返回false。
这些定义都是自然合理的,但确保这些性质成立并遵循Java的约定,同时又避免在实现时做无用功却并不容易。一般可以通过下面步骤做到这一点。
-
如果该对象的引用和参数对象的引用相同,返回true。这项测试在成立时能够勉去其他所有测试工作。
-
如果参数为空(null),根据约定返回false(还可以在下面的代码中避免空引用)。
-
如果两个对象的类不同,返回false。要得的一个对象的类,可以使用getClass()方法。请注意是使用==来判断Class类型的对象是否相等,因为同一种类型的所有对象的getClass()方法一定能够返回相同的类型。
-
将参数对象的类型从Object转换到Date(因为前一项测试已经通过,这种转换必要成功)。
-
如果任意实例变量的值不相同,返回false。
二 实战
@Override
public String toString() {
return month + "/" + day + "/" + year;
}
/**
* Compares this date to the specified date.
*
* @param other the other date
* @return {@code true} if this date equals {@code other}; {@code false} otherwise
*/
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (other == null) return false;
if (other.getClass() != this.getClass()) return false;
Date that = (Date) other;
return (this.month == that.month) && (this.day == that.day) && (this.year == that.year);
}