java.lang.Object 类作弊。它将相等性(由equals 确定)定义为对象标识(由== 确定)。因此,除非您在子类中覆盖 equals,否则您的类的两个实例是“相等的”,如果它们碰巧是同一个对象。
为此相关的哈希码由系统函数System.identityHashCode 实现(它不再真正基于对象地址——曾经是这样吗?——但可以认为是以这种方式实现的)。
如果您覆盖equals,那么hashCode 的这种实现就不再有意义。
考虑以下示例:
class Identifier {
private final int lower;
private final int upper;
public boolean equals(Object any) {
if (any == this) return true;
else if (!(any instanceof Identifier)) return false;
else {
final Identifier id = (Identifier)any;
return lower == id.lower && upper == id.upper;
}
}
}
这个类的两个实例被认为是相等的,如果它们的“lower”和“upper”成员具有相同的值。由于相等现在由对象成员确定,我们需要以兼容的方式定义hashCode。
public int hashCode() {
return lower * 31 + upper; // possible implementation, maybe not too sophisticated though
}
如您所见,我们在hashCode 中使用相同的字段,我们在确定相等性时也会使用这些字段。将哈希码基于所有成员通常是一个好主意,在比较相等性时也会考虑这些代码。
请考虑以下示例:
class EmailAddress {
private final String mailbox;
private final String displayName;
public boolean equals(Object any) {
if (any == this) return true;
else if (!(any instanceof EmailAddress)) return false;
else {
final EmailAddress id = (EmailAddress)any;
return mailbox.equals(id.mailbox);
}
}
}
由于这里,相等性仅由mailbox 成员确定,哈希码也应仅基于该成员:
public int hashCode() {
return mailbox.hashCode();
}