equals和hashCodeequals 和 hashCode 都是 Object 类拥有的方法,包括 Object 类中的 toString 方法打印的内容也包含 hashCode 的无符号十六进制值 。
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());}复制代码由于需要比较对象内容,所以我们通常会重写 equals 方法,但是重写 equals 方法的同时也需要重写 hashCode 方法,有没有想过为什么?
因为如果不这样做的话,就会违反 hashCode 的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这类集合包括 HashMap 和 HashSet 。
这里的通用约定,从 Object 类的 hashCode 方法的注释可以了解,主要包括以下几个方面,
从理论上来说如果重写了 equals 方法而没有重写 hashCode 方法则违背了上述约定的第二条,相等的对象必须拥有相等的散列值 。
但是规则是大家默契的约定,如果我们就喜欢不走寻常路,在重写了 equals 方法后没有覆盖 hashCode 方法,会产生什么后果吗?
我们自定义一个 Student 类,并且重写了 equals 方法,但是我们没有重写 hashCode 方法,那么当调用 Student 类的 hashCode 方法的时候,默认就是调用超类 Object 的 hashCode 方法,根据随机数返回的一个整型值 。
public class Student { private String name; private String gender; public Student(String name, String gender) { this.name = name; this.gender = gender; } //省略 Setter,Gettter@Override public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof Student) { Student anotherStudent = (Student) anObject; if (this.getName() == anotherStudent.getName() || this.getGender() == anotherStudent.getGender()) return true; } return false; }}复制代码我们创建两个对象并且设置属性值一样,测试下结果:
public static void main(String[] args) { Student student1 = new Student("小明", "male"); Student student2 = new Student("小明", "male"); System.out.println("equals结果:" + student1.equals(student2)); System.out.println("对象1的散列值:" + student1.hashCode() + ",对象2的散列值:" + student2.hashCode());}复制代码得到的结果
【对Java中HashCode方法的深入思考】equals结果:true对象1的散列值:1058025095,对象2的散列值:665576141复制代码我们重写了 equals 方法,根据姓名和性别的属性来判断对象的内容是否相等,但是 hashCode 由于是调用 Object 类的 hashCode 方法,所以打印的是两个不相等的整型值 。
如果这个对象我们用 HashMap 存储,将对象作为 key,熟知 HashMap 原理的同学应该知道,HashMap 是由数组 + 链表的结构组成,这样的结果就是因为它们 hashCode 不相等,所以放在了数组的不同下标,当我们根据 Key 去查询的时候结果就为 null 。
推荐阅读
- 阿里架构总监13张PPT一次讲透中台架构
- 关于并发框架 Java原生线程池原理及Guava与之的补充
- 中国的收费站一天可以收多少钱 中国收费站一天的收入
- java数据结构及算法总结
- Linux中的xargs命令
- PHP删除数组中指定值的元素的方法
- 金士顿和闪迪u盘对比 金士顿u盘和闪迪u盘哪个耐用
- 茶中为什么会喝出酸味
- redis是如何存储对象和集合的
- Java中的HashCode方法与内存泄漏问题,你了解过吗?
