为什么重写equals()要重写hashcode()
答:hashcode判断是equals判断的先决条件;所以对象重写了equals()方法,需要重写hashcode()方法
详细答案:
首先了解下对象的描述:对象具有状态、行为和标识。
状态为对象的内部数据;行为为对象的方法;标识为对象与其它对象唯一区别的方式。
那么接下来聊一聊标识,严格意义上来讲,对象的标识为内存中唯一的地址;但是现实生活中,标识往往是一个区间的范围的对应;例如小明数学成绩为95和小红数学成绩为98,那么小明和小红数学成绩标识均为优秀。面向对象语言是对现实的一种抽象,所以从代码角度来讲,标识就是对象的hashcode;我们知道hashcode算法是一种压缩算法(不同长度的输入,总是有相同长度的输出),压缩算法的输出空间是远小于输入空间,这样必然会有这样一种想象,不同的对象,他们的hashcode是相同的。如果需要比较对象内容是否相同,那么首先就要判断对象的标识是否相同,如果标识都不同,那么对象内容就没有比较的意义了(如比较小明和小红的数学成绩是否相等,首先要判断数学成绩是否均为优秀,若为优秀,再比较两者成绩是否相等)。
由上可知:hashcode判断是equals判断的先决条件;所以对象重写了equals()方法,需要重写hashcode()方法
Object源码分别都有 hashcode()和equals()方法;为什么还需要重写?
答:Object 的 equals方法判断的是对象是否为同一个对象;然后现实业务需要判断的是内容是否相等,所以需要重写equals()方法,而重写equals()方法也需要重写它的先决条件判断hashcode()方法。
详细答案:
首先看下Object类相关源码
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
hashCode() 方法实现底层为native方法(c语言实现);该处不做深究,可以理解为hashcode返回对象内存地址的映射值;
equals() 方法实现,使用的是 == 比较两个对象;== 比较的是 栈中对象引用的内容,栈中内容对象引用内容其实就是对象在堆中的内存地址;所以Object中equals() 比较的是对象是否是同一个对象;然而现实业务并不一定符合该场景,现实业务往往比较的是内容是否相等,而不是对象是否是同一个(实际上equals方法的本意就是比较内容是否相同,如String等);所以现实业务需要比较内容是否相等,就需要重写equals();而重写equals()方法,就需要重写它的先决条件判断hashcode()方法。