为什么重写equals时必须重写hashCode方法?
首先,java是一门面向对象编程语言,所有的类都会默认继承Object类,而Object的中文意思就是”对象“。Object类有这么两个方法:
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
doc文档中这样解释:如果两个对象调用equals方法返回的结果是true,那么这两个对象调用hashCode方法返回的结果也必然相同。因此每当重写equals方法时,hashCode方法也需要重写,以便维护上一条规约。
来看下面示例:
package com.example.rookie.demo;
import java.util.Objects;
/**
* @author
* @date 2021/9/9 14:30
*/
public class ObjectDemo {
private String name;
private int age;
public ObjectDemo() {
}
public ObjectDemo(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
ObjectDemo od = (ObjectDemo) obj;
return age == od.age && Objects.equals(name, od.name);
}
}
public class Test{
public static void main(String[] agrs){
ObjectDemo od1 = new ObjectDemo("张三", 18);
Map<ObjectDemo, Integer> scores = new HashMap<>();
scores.put(od1, 98);
ObjectDemo od2 = new ObjectDemo("张三", 18);
System.out.println(scores.get(od2));
}
}
以上结果输出为null,而不是98,原因就在于重写equals方法的时候没有重写hashCode方法,equals方法虽然认定名字和年纪相同就是同一个学生,但他们本质上是两个对象,hashCode并不相同。
package com.example.rookie.demo;
import java.util.Objects;
/**
* @author
* @date 2021/9/9 14:30
*/
public class ObjectDemo {
private String name;
private int age;
public ObjectDemo() {
}
public ObjectDemo(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
ObjectDemo od = (ObjectDemo) obj;
return age == od.age && Objects.equals(name, od.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
}
public class Test{
public static void main(String[] agrs){
ObjectDemo od1 = new ObjectDemo("张三", 18);
Map<ObjectDemo, Integer> scores = new HashMap<>();
scores.put(od1, 98);
ObjectDemo od2 = new ObjectDemo("张三", 18);
System.out.println(scores.get(od2));
}
}
再次执行main方法,输出为:98