equals()方法用于确定两个对象是否被认为是“相等的”。默认情况下,它比较引用(即==),但通常类(例如实体、值对象)需要基于数据的逻辑比较。
何时重写:
要求:
示例:
public class Person { private String email; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(email, person.email); } @Override public int hashCode() { return Objects.hash(email); } }
如果两个对象在equals()中相等,它们的hashCode()是否总是相同的?
回答: 是的!这是Java合同的要求。但是反之则不然:两个具有相同hashCode的对象可能在equals()中不相等——哈希码可能会因不同对象而相同(冲突)。
错误示例:
person1.equals(person2); // true person1.hashCode() != person2.hashCode(); // 错误!
故事
在企业应用中,User实体被放入HashSet。重写了equals,但没有重写hashCode。在修改影响equals的字段后,HashSet“丢失”了这个对象:使用contains方法的搜索返回false,即使数据相同。
故事
在IoT项目中,实体最初仅按id进行比较,之后逻辑更改为考虑名称的equals。HashMap开始表现得不可预测,在更新键时出现重复项——由于实现版本的混合违反了equals/hashCode的合同。
故事
在编写比较订单的API时,两个不同的类实现了自己的equals,一个调用getClass(),另一个使用instanceof。这导致了不对称的订单比较,并在使用集合和业务逻辑时出现了错误。