Object.equals() 默认比较内存地址,需重写以支持字段值相等判断;重写必须遵守自反性、对称性、传递性、一致性及对null处理五项约定,并须配套重写hashCode()。

Java 中 Object.equals() 默认行为是比较两个对象的内存地址(即引用是否指向同一块堆内存),这在绝大多数业务场景下无法满足“内容相等”的语义需求。因此,只要类需要按字段值判断相等性(比如两个 User 对象姓名和 ID 都相同就视为同一个用户),就必须重写 equals() 方法。
默认 equals() 实际调用的是 == 运算符
Object 类中 equals() 的默认实现是:
return (this == obj);
}
它本质就是引用比较。这意味着即使两个对象所有字段一模一样,只要不是同一个 new 出来的实例,equals() 就返回 false。
- 例如:
new String("hello").equals(new String("hello"))返回true,是因为String已重写equals(); - 但
new User("Alice", 1).equals(new User("Alice", 1))默认返回false,因为它们是不同对象。
不重写 equals() 会导致集合操作异常
很多核心集合类(如 HashSet、HashMap、ArrayList.contains())依赖 equals() 判断元素是否存在或重复。若未重写,会出现意料之外的行为:
Set<user> set = new HashSet();<br>set.add(new User("Tom", 25));<br>set.contains(new User("Tom", 25)); // 返回 false —— 虽然内容相同,但没被识别为存在</user>Mapmap = new HashMap();
map.put(new User("Jerry", 30), "Engineer");
map.get(new User("Jerry", 30)); // 返回 null —— 键查不到,因为 equals 不匹配
重写 equals() 必须遵守通用约定
仅仅重写还不够,必须满足以下五点,否则可能破坏集合一致性或引发运行时错误:
-
自反性:对任意非 null 引用
x,x.equals(x)必须返回true; -
对称性:若
x.equals(y)为true,则y.equals(x)也必须为true; -
传递性:若
x.equals(y)和y.equals(z)均为true,则x.equals(z)也应为true; - 一致性:多次调用结果不变(前提对象状态未修改);
-
对 null 的处理:对任意非 null 引用
x,x.equals(null)必须返回false。
实践中建议使用 IDE 自动生成(如 IntelliJ 的 Alt+Insert → equals and hashCode),并确保参与比较的字段与业务语义一致(例如是否忽略空格、大小写,是否包含敏感字段等)。
重写 equals() 通常需配套重写 hashCode()
如果两个对象通过 equals() 判定为相等,它们的 hashCode() 必须相同。否则放入哈希表时会散列到不同桶中,导致查找失败。
- 例如:
new User("Bob", 28)和new User("Bob", 28)若equals()返回true,但hashCode()返回不同值,则在HashMap中无法正确检索; - IDE 自动生成
equals()时一般会同步生成匹配的hashCode(),基于相同字段计算。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











