我正在写一个应用程序,它有一个"成就"系统,类似于Stack Overflow的徽章。我也在使用SugarORM来存储成就的进展。这是Achievement
类:
public class Achievement extends SugarRecord<Achievement>{
@StringRes
public int shortNameId;
@StringRes
public int descriptionId;
public int progressNow;
public int fullProgress;
//I am afraid that Sugar ORM will ignore private fields
//so I made them public. Please tell me if Sugar ORM does
//not ignore those.
}
现在我想覆盖equals
。这很容易。
@Override
public boolean equals (Object other) {
if (other == null) return false;
if (!(other instanceof Achievement)) return false;
Achievement a = (Achievement)other;
return a.shortNameId == shortNameId &&
a.descriptionId == descriptionId &&
a.fullProgress == fullProgress;
}
然后我想起来,如果我覆盖equals
,我应该始终覆盖hashCode
。根据Joshua Bloch的Effective Java,我编写了如下hashCode
方法:
@Override
public int hashCode () {
int result = 17;
result = result * 31 + shortNameId;
result = result * 31 + descriptionId;
result = result * 31 + fullProgress;
return result;
}
然后我想我应该把equals
的实现改为
@Override
public boolean equals (Object other) {
if (other == null) return false;
if (!(other instanceof Achievement)) return false;
Achievement a = (Achievement)other;
return a.hashCode() == hashCode ();
}
之后,我想如果我错误地覆盖了hashCode
,equals
也不会工作。然而,上面的实现对我来说似乎是"正确的",因为我认为哈希码是使对象相等的东西。
附言:别告诉我这是个人喜好。我认为这一定有一个标准,对吧?而且我也非常愿意遵守标准。
一般来说,a.hashCode()==b.hashCode()
并不意味着a.equals(b)
必须为真。因此,您不应该依赖hashCode
来确定相等性。
然而,另一个方向是正确的。如果a.equals(b)
,则a.hashCode()
必须等于b.hashCode()
。