在Java语言中并不能直接获取变量的地址,但是能获取到hashcode,hashcode是根据变量的地址或随机或值(java自带的类,比如String)等参数通过散列函数计算得到的,直接对对象引用进行输出就是hashcode,对于重写过的hashcode,不同对象的 hashCode 可能相同,但 hashCode 不同的对象一定不相等,所以使用 hashCode 可以起到快速初次判断对象是否相等的作用,然后再利用equals来判断是否真的相等(逻辑上)。
JAVA中对象都继承Object类,其中原生具有equals函数和hashcode函数,其中hashcode由地址计算得来,equal函数判断原则就是直接比较两个对象的hashcode是否一致,而实际应用中我们利用equals的目的是逻辑上判断两个对象值是否相同,但是由于(自定义变量)默认的hashcode是由地址计算的,因此即使值相同的两个不同引用的hashcode肯定是不一样的,此时再用equals判断,无论何时得到的都是false,所以此时我们应该首先重写hashcode方法,统一相同value的对象的hashcode一致,但是由于不同对象的 hashCode 可能相同,还是要进行下一步对value的判断,此时应该调用equals方法,如果equals方法也一致,那么则判断两个对象相等。
为什么要重写equals也要重写hashcode?
如果只重写了 equals 方法,那么默认情况下,Set 进行去重操作时,会先判断两个对象的 hashCode 是否相同,此时因为没有重写 hashCode 方法,所以会直接执行 Object 中的 hashCode 方法,而 Object 中的 hashCode 方法对比的是两个不同引用地址的对象,所以结果是 false,那么 equals 方法就不用执行了,直接返回的结果就是 false:两个对象不是相等的,于是就在 Set 集合中插入了两个相同的对象。
但是,如果在重写 equals 方法时,也重写了 hashCode 方法,那么在执行判断时会去执行重写的 hashCode 方法,此时对比的是两个对象的所有属性的 hashCode 是否相同,于是调用 hashCode 返回的结果就是 true,再去调用 equals 方法,发现两个对象确实是相等的,于是就返回 true 了,因此 Set 集合就不会存储两个一模一样的数据了,于是整个程序的执行就正常了。
总结
hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的,采用这种方式的原因是可以提高程序插入和查询的速度,如果在重写 equals 时,不重写 hashCode,就会导致在某些场景下,例如将两个相等的自定义对象存储在 Set 集合时,就会出现程序执行的异常,为了保证程序的正常执行,所以我们就需要在重写 equals 时,也一并重写 hashCode 方法才行,或者先重写hashcode,再重写equals。
可以把hashcode看成一种标识码。