编程Java开发者

Java中hashCode()方法的重写机制是如何工作的,遵循哪些规则,违反这些规则可能会导致哪些严重错误?

用 Hintsage AI 助手通过面试

答案。

重写hashCode()方法与重写equals()密切相关:这两个方法为在HashMapHashSetHashtable等依赖于比较和哈希函数的集合中正确使用对象奠定了基础。

规则:

  • 如果重写equals(),一定要重写hashCode()
  • 通过equals()相等的对象必须返回相同的hashCode()
  • 建议使用标准的哈希生成方法,例如Objects.hash()或IDE模板,以避免错误。
  • hashCode()必须在对象的"生命周期"内返回相同的值(如果参与hashCode的字段是不可变的)。
class User { private String name; public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(name, user.name); } public int hashCode() { return Objects.hash(name); } }

陷阱问题。

问题: "如果两个通过equals()不同的对象返回相同的hashCode(),这会是一个错误吗?"

答案: 不是,这是可以接受的。哈希冲突是可解决和可预期的——重要的是,如果对象在equals上相等,则它们的hashCode必须相同。如果不同的equals对象产生相同的hashCode,集合将变得更慢(由于更多的冲突),但仍然是正确的。

由于不了解这一主题而导致的实际错误示例。


故事

在金融软件中,多个字段进行项目比较,但只重写了equals()。对象存储在HashSet中,出现了重复,因为hashCode()没有被重写且使用了默认(对于每个实例不同)。


故事

在仓库管理系统中,在添加业务逻辑更改后扩展了equals(),但忘记更新hashCode()。具有不同hashCode但equals=true的对象在HashMap中丢失(无法通过键找到),导致重大财务错误。


故事

在Web应用程序中在计算hashCode时使用了可变字段。更新内部字段的值时,哈希值发生变化,导致对象在HashSet/HashMap中“丢失”:无法通过标准方法找到或删除,导致内存泄漏和错误。