equals()方法和hashCode()方法是否需要同时重写
问题分析
在讨论这个问题之前,先给出结论:如果重写其中一个方法,则另外一个方法也必须重写.
我们都知道,如果一个类创建了两个实例,相比较这两个实例是否相等需要重写Object类的equals()方法。
那么equals方法是怎么执行的呢,下面来分析以下,首先拿大家都非常熟悉的String类型做说明
string重写的equals()方法源码:
public boolean equals(Object anObject) {
// 首先,判定两个待比较的数据的地址值是否一致,若一致返回true
if (this == anObject) {
return true;
}
//如果待比较的数据可以向下转型为String, 则挨个字符对比,全部一致返回true
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
//若无法向下转型,返回false
return false;
}
再看Objects的equals()方法怎么做的,这个方法非常经典,由于它容忍空指针,所以平常比较字符串的时候大家都很喜欢用
public static boolean equals(Object a, Object b) {
//非常简单,如果地址值一致则返回true,如果a自身的equals()方法判定与b相同也返回true
return (a == b) || (a != null && a.equals(b));
}
那么现在如果自定义一个类重写equals,重写的规则是什么呢?定义一个People类
package com.cmdc.review.javap;
import java.util.Objects;
/**
* @author : wuwensheng
* @date : 9:55 2020/6/30
*/
public class People {
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;//如果两个对象的地址值相同 直接return true
if (o == null || getClass() != o.getClass()) return false;//如果传递的对象类型和本类对象类型不一致 直接return false
People people = (People) o;
//具体开始比较people的各个属性,基本类型使用==,其余类型调用其自身重写的equals()方法
return age == people.age &&
Objects.equals(name, people.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
以上就是对equals()方法的说明,无论一个类有多少属性,equals()方法的套路都是一致的,先比较地址值,再向下转型挨个字段比较。
hashCode()方法说明
hashCode()是object类的方法,如果不重写hashCode()方法,那么就是在用父类Object的hashCode()方法,Object的hashCode()会用两个对象的地址值做hash运算(是不是地址值有争论,但是我觉得可以按照地址值)。若重写hashCode(),则根据对象的各个属性得出hash码值。
Object的源码
public native int hashCode();
重写hashCode()将会执行的源码
@Override
public int hashCode() {
// 重写之后调用Objects的hash()方法
return Objects.hash(name, age);
}
点进去调用Arrays的hashCode()方法
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
最后看Arrays的hashCode()方法怎么操作的
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
因此,hashCode重写之后是根据各个属性计算得出的哈希码值
结论
如果仅仅重写了equals而不重写hashCode,那么可能得出的结论是两个对象的
equals结果相同但hashCode不同,这是很荒唐的
示例代码:
所以,两个方法必须全部重写!
上一篇: 基于阈值分解的多级中值滤波
下一篇: cpu的组成中不包含什么
推荐阅读
-
why在重写equals时还必须重写hashcode方法分享
-
why在重写equals时还必须重写hashcode方法分享
-
重写hashCode()和equals()方法详细介绍
-
重写hashCode()和equals()方法详细介绍
-
Java连载57-equals重写、finalize方法、hashCode方法
-
一文搞懂hashCode()和equals()方法的原理
-
荐 java父类-Object类-equals与==-方法的重载和重写-游离块-this关键字
-
java中重写equals()方法的时候为什么要重写hashCode()方法?
-
哈希表中为什么要重写hashCode与equals方法
-
Java中为什么要重写hashCode方法和equals方法?