一:众所周知,hashCode()方法与equals()方法必须要一起重写,那么为什么两者必须要同时重写呢?不同时重写不行吗?
二:hashCode()方法与equals()方法的简单介绍。
1.hashCode():该方法属于Object类,是由native关键字修饰的方法,也就是说,该方法是本地方法,是由底层非java语言实现的。该方法的实现实际是会根据对象的内存地址,返回一个int类型的数字。通过比对两个对象的hash码,就可以知道两者是否是同一个对象了。
实际上在设计hash码时有几条规则
(1).同一个对象的hash码必须相同
(2).hash码不同,则对象一定不相等
(3).不同对象的hash码不一定不相同
简而言之:hash码不同,就一定不是同一个对象,但是hash码相同,不一定是同一个对象。那么当hash码相同时,如何判断两个对象是否是同一个对象呢?先来看看equals()方法。
2.equals():该方法默认逻辑是调用“==”实现。也就是说,如果没有重写该方法,则该equals()方法是通过“==”实现的。而“==”就是判断两个对象的内存地址是否相等,换言之,equals()方法,也是用来判断两个对象是否相等的。
也就是说:hashCode()与equals()都是用来比较两个对象是否相等的方法。默认情况下,equals()中认为相等的对象是同一个对象,那么他们的hash码也是相等的,也就满足了哈希原则中的如果两个对象相等,则哈希码一定相等。该原则不能打破,因此,equals()方法与hashCode()方法必须同时重写,从而保证该原则。
三:如果没有同时重写会发生什么?
1.重写equals()而不重写hashCode()
会造成两个逻辑上相等(equals认为相等)的结果可能返回不一样的哈希码。如果String类没有重写hashCode(),那么字面量相等,但是不是同一个实例对象的话,两者的哈希码会不同(String中,equals()判断两个对象是否相同的逻辑是看字面量是否相等)。那么在HashMap中,字面量相等的key,就会被散列到不同的位置
因此:String中的hashCode()的重写逻辑就是根据字面量来生成哈密码,保证字面量相同,返回的哈希码是一致的
2.重写hashCode()而不重写equals()
又拿String来说,若重写hashCode()而不重写equals(),则在HashMap中,字面量相等的key,即使会散列到相同的位置,但是也无法覆盖旧值(如果元素散列的位置相同,HashMap会调用equals()方法,来判断是否需要覆盖旧值)
因此:想要作为HashMap的key,必须要重写hashCode()方法以及equals()方法,保证同一个对象的哈希码相同;同一个哈希码可以通过equals来判断是否是同一个对象
简而言之,两个方法同时重写,就是为了保证equals中认为相等的两个对象,哈希码也相等(相同的对象可以散列到同一个位置)。并且,当哈希码相同时,equals()可以进一步判断两个对象是否相等。(哈希原则中,哈希码相等,不一定是同一个对象)