我们知道在Java中==
是比较两个对象的地址而equals()
是比较两个对象的值
但是如果我们自定义一个类的话,不重写这个类的equals()
话,是怎么样的呢?
我们点开源码可以发现实际上还是比较两个对象的地址,所以当我们自定义一个类的时候需要重写这个类的equals()
重写了equals()
以后这个类实例化之后比较的才是值而不是内存地址
public boolean equals(Object obj) {
return (this == obj);
}
由于知道了原生的equals()
实际上还是比较的是内存地址,所以当我们自定义一个类以后需要重写这个类的equals()
,只有重写了equals()
以后这个类实例化之后比较的才是值而不是内存地址
问题来了为什么重写了重写了equals()
为什么又要重写hashcode()
呢?
首先我们要清楚一点原生的hashcode()
实际上是用对象的内存来生成hashcode
的,这一点可以点开源码来证明
hashcode
又是为了应对集合类的使用而创建的,用于找到对应的集合中对应的位置后进行添加查找等一系列操作。
假设有这么一个场景,有一个类重写了equals()
并没又重写hashcode
通过这个类实例化出两个对象,这两个对象里面的值是相同,但是没有重写hashcode()
,由于这两个对象的内存地址是不同的,所以生成的hashcode
也是不同的,这就导致了两个相同的值通过不同的hashcode
插入到了同一个集合里面的不同位置,这就造成了程序混乱。
为了避免这种情况的发生,我们就得重写hashcode
方法了。
下面通过一个例子来演示怎么重写equals
和hashcode
方法
class Student{
int age;
String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
}
对于equals()
来说,首先验证两个对象的地址是否相同,如果相同直接返回true,如果不同那么就将这个对象转换成相同的对象进行比较,然后再对值进行对比来确认是返回true还是false
对于hashcode()
来说,我们不能再根据内存地址来生成hashcode
,而是要根据类里面相应的属性生成相应的hashcode
这样才能保证当两个对象里面值相同的时候生成的hashcode
也是相同的,避免程序异常问题的发生