1.什么时候需要覆写equals和hashCode方法?
当类具有自己特有的逻辑相等概念,而且超类还没有覆盖equals方法时,简单说就是需要比较两个对象在逻辑上是否相等。
2.覆写equals方法的要求
需要满足以下五个特性:
- 自反性:x非null,
x.equals(x)返回true - 对称性:x,y非null,
x.equals(y)和y.equals(x)比较结果相同 - 传递性:x,y,z非null,
x.equals(y)为true,y.equals(z)为true,则x.equals(z)为true - 一致性:对象在equals方法中比较的关键域的值没有变,多次调用结果相同
- x非null,x.equals(null)返回false
3.覆写equals和hashCode示例
覆写equals方法的同时应该覆写hashCode方法,否则对象用作HashMap和HashSet中时会有问题,两个方法中用到的关键域应该一致。
import java.util.Objects;
public class ScorePoint {
private String grade;
private String team;
private int score;
// 第一个关键域赋值给result,其余关键域哈希值依次用result = 31 * result + hashcode累加,如果域为null,它的hashCode可以看作是0
@Override
public int hashCode() {
int result = 0;
if (grade != null) {
result = grade.hashCode();
}
if (team != null) {
result = 31 * result + team.hashCode();
}else{
result = 31 * result;
}
result = 31 * result + Integer.hashCode(score);
return result;
}
// 简单实现,质量与上面的方式相当,性能不好,对性能没有过高要求可以使用
@Override
public int hashCode(){
Objects.hash(grade, team, score);
}
@Override
public boolean equals(Object obj) {
// 1.性能优化,比较操作可能开销较大
if (this == obj) {
return true;
}
// 2.类型判断,同时如果obj为null,instance of会返回false
if (!(obj instanceof ScorePoint)) {
return false;
}
// 3.转成正确的类型
ScorePoint scorePoint = (ScorePoint) obj;
// 4.比较关键域
return (grade != null && grade.equals(scorePoint.grade)) &&
(team != null && team.equals(scorePoint.team)) &&
score == scorePoint.score;
}
}
本文主要参考《Effective Java》