当我们需要比较两个对象的内容是否相同时,就需要用到equals()方法。而在使用equals()方法时,如果我们没有重写该方法,那么默认的实现是比较两个对象的内存地址是否相同。
然而,有时候我们并不想比较内存地址,而是希望比较对象的内容是否相同。这时就需要重写equals()方法了。下面是重写equals()方法的攻略:
为什么需要重写equals()方法
需要重写equals()方法的主要原因是当我们对自定义的类进行比较时,默认的equals()方法无法判断对象的内容是否相同。
例如,假设我们有一个Employee类,里面包含了员工编号、姓名等基本信息。当我们需要比较两个Employee对象时,如果不重写equals()方法,那么默认的比较方式就只会比较两个对象的内存地址,而不会比较对象的内容是否相同。这样就会导致我们无法得到正确的比较结果。
如何重写equals()方法
重写equals()方法需要遵守以下原则:
- 对称性:如果x.equals(y)返回true,那么y.equals(x)也应该返回true
- 自反性:x.equals(x)永远返回true
- 传递性:如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也应该返回true
- 一致性:如果x和y的内容没有发生改变,那么无论调用多少次x.equals(y),都应该得到相同的结果
- 对null的处理:x.equals(null)永远返回false
以下是一个示例Employee类的重写equals()方法的实现:
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Employee other = (Employee) obj;
if (!Objects.equals(this.empId, other.empId)) {
return false;
}
if (!Objects.equals(this.firstName, other.firstName)) {
return false;
}
if (!Objects.equals(this.lastName, other.lastName)) {
return false;
}
return true;
}
在这个实现中,我们先判断传入的对象是否为null,然后再判断两个对象的类是否相同。最后,我们逐一比较每个属性,如果所有属性均相同就返回true,否则返回false。
为什么需要重写hashCode()方法
在Java中,每个对象都有一个对应的哈希码(hashCode),它是一个32位整数。当我们需要将对象存储到集合类中时,往往需要根据对象的hashCode来快速找到该对象在集合中的位置。
Java中的集合类(如HashMap、HashSet)在实现时,使用哈希表(hash table)来存储对象。哈希表的实现需要利用对象的哈希码来确定对象在哈希表中所处的位置。
默认情况下,每个对象的hashCode是根据对象的内存地址自动生成的。也就是说,如果我们不重写该方法,那么相同内容的对象在哈希表中还是会被保存成不同的实例,不同内容的对象可能被映射到同一个位置,从而影响效率。
为了解决这个问题,我们需要重写hashCode()方法。
如何重写hashCode()方法
在重写hashCode()方法时,我们需要遵守以下原则:
- 如果两个对象通过equals()方法比较相等,那么它们的hashCode()方法的返回值也应该相等
- hashCode()方法的返回值应该具有足够的随机性,以便在哈希表中能够均匀分布
以下是一个示例Employee类的重写hashCode()方法的实现:
public int hashCode() {
int hash = 7;
hash = 71 * hash + Objects.hashCode(this.empId);
hash = 71 * hash + Objects.hashCode(this.firstName);
hash = 71 * hash + Objects.hashCode(this.lastName);
return hash;
}
在这个实现中,我们先定义了一个base值为7,然后将每个属性的hashCode()值(使用Objects.hashCode()方法计算)乘以一个常数(这里是71),并将结果与base值相加,最终得到一个整型值。这个整型值就是该对象的哈希码。