必须重写equals方法,因object默认仅作引用比较(==),无法满足业务上按内容判等的需求;需严格遵守自反性、对称性、传递性、一致性及null处理五项契约,并同步重写hashcode,且二者须基于相同字段,推荐用getclass()类型检查和objects.equals/objects.hash。

要让自定义对象按业务内容判断相等,必须重写 equals 方法,不能依赖 Object 默认的引用比较。核心是:用哪些字段决定“逻辑上相等”,就只比哪些字段,并严格遵守五项契约。
为什么不能直接用默认 equals
Object 类里的 equals 就是 ==,只看是不是同一个对象实例。比如两个 new Person("张三", 25) 实例,内容完全一样,但默认 equals 返回 false。这不符合业务需求——你肯定希望 ID 相同的用户被视为同一人。
重写 equals 的标准步骤
以 Person 类为例,约定 id 和 name 决定相等性:
- 先检查是否为同一引用:if (this == obj) return true;
- 再判空和类型:if (obj == null || getClass() != obj.getClass()) return false;(推荐用 getClass() 而非 instanceof,避免子类打破对称性)
- 强转后逐字段比较:Person other = (Person) obj; 然后用 Objects.equals(id, other.id) 和 Objects.equals(name, other.name) ——它自动处理 null,安全又简洁
必须同步重写 hashCode
只要重写了 equals,就必须重写 hashCode,且两者基于完全相同的字段。否则放进 HashMap 或 HashSet 会出问题:
- 比如 equals 比了 id + name,但 hashCode 只用了 id → 两个 name 不同但 id 相同的对象,equals 返回 false,但 hashCode 却一样,可能被塞进同一个桶,导致查找失败或重复存储
- 最稳妥写法:return Objects.hash(id, name);(JDK 7+ 提供,内部已优化)
容易踩坑的细节
这些不是“可能错”,而是“一定破坏集合行为”:
- 在 equals 或 hashCode 中使用可变字段(如 status、lastLoginTime)→ 对象修改后,哈希值变了,但 HashMap 里位置没更新,再也找不到了
- 用 instanceof 做类型检查 → 若 Person 有子类 Student,person.equals(student) 为 true,但 student.equals(person) 可能为 false,违反对称性
- 字段比较时手动写 a == b 处理引用类型 → 一旦 a 或 b 是 null,直接 NPE;必须用 Objects.equals
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











