Java中调用Object#equals()时对象必同hashCode?equals内需校验吗?
1. 调用Object#equals()时,两个对象的hashCode值一定相同吗?
首先明确:不一定。Java语言规范仅要求:如果两个对象通过equals()判定为相等,那么它们的hashCode必须相等;但equals()方法的调用本身,和两个对象的hashCode是否相等没有强制绑定关系——你完全可以手动调用obj1.equals(obj2),不管这两个对象的hashCode是否一致,方法都会执行。
你看到的HashMap相关描述:
hashCode() allows sorting objects by their hash values, and then the Object#equals method only needs to be invoked when objects share the same hash value.
这是哈希容器(如HashMap、HashSet)的内部优化逻辑,不是Java对equals()方法的强制要求。这类容器为了减少equals()的调用次数(equals通常比hashCode计算更耗时),会先比较hashCode:如果hashCode不同,直接判定两个对象不相等,不会调用equals();只有hashCode相等时,才会调用equals()做最终确认。
但存在例外场景:如果某个类没有正确重写hashCode(),导致两个equals()相等的对象hashCode不同,HashMap这类容器会把它们当成不同对象存储(属于程序逻辑错误),但此时你手动调用equals(),依然会返回true,哪怕hashCode不同。另外,你完全可以绕过容器直接手动调用equals(),这时候不管hashCode是否相同,方法都会执行。
2. 在equals()方法中校验两个对象的hashCode值是否有意义?
看你提供的示例代码,这行return this.hashCode() == inputObj.hashCode();几乎没有意义,甚至可能引发问题,分情况说明:
情况1:hashCode基于bytes数组计算
如果你的类中hashCode()是通过Arrays.hashCode(bytes)实现的,那么当Arrays.equals(this.bytes, inputObj.bytes)返回true时,两个对象的hashCode必然相等。此时这行代码完全是重复校验,不仅没有任何好处,还会额外执行一次hashCode计算,降低方法效率。
情况2:hashCode不基于bytes数组计算
如果hashCode的计算依赖其他字段(而非bytes),这行代码会直接破坏equals()的逻辑:当两个对象的bytes数组完全相同,但其他影响hashCode的字段不同时,equals()会返回false,这和前面的校验逻辑矛盾,也违反了Java的equals/hashCode约定——业务逻辑上应该相等的对象,equals()却返回false,会导致HashMap等容器行为异常。
额外说明
退一步说,就算想用hashCode做前置校验,也应该把它放在equals()方法的最前面(比如判断instanceof之后),这样能快速排除hashCode不同的对象、提升效率。但在完成核心字段(bytes)的校验后再比较hashCode,完全是画蛇添足。
内容的提问来源于stack exchange,提问作者HyperVol

