重写equals方法须满足自反性、对称性、传递性、一致性,且x.equals(null)返回false;应先用==拦截null和同一引用,再用instanceof检查类型,最后用Objects.equals()逐字段比较,并同步重写hashCode。

重写 equals 方法必须同时满足自反性、对称性、传递性、一致性,且对任何非 null 引用 x,x.equals(null) 必须返回 false。最稳妥的方式是使用 Objects.equals() 辅助判断,并严格遵循“先类型检查、再字段比较”的顺序。
第一步:处理 null 和同一引用
开头必须快速拦截两种情况:参数为 null,或与当前对象是同一个实例(即 this == obj)。这能避免空指针异常,并提升性能。
-
错误写法:先强制转型再判空 —— 可能抛
NullPointerException -
正确写法:用
==先比引用,再用instanceof判类型,最后转型
第二步:严格进行类型检查
必须用 obj instanceof YourClass(推荐)或 getClass() == obj.getClass()。前者支持子类向上兼容(Liskov 替换原则),后者更严格但可能破坏多态语义。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 若用
getClass(),子类对象调用父类equals永远返回false,即使字段值完全相同 - 实践中,除非明确要求“仅同类相等”,否则优先用
instanceof
第三步:逐字段比较,用 Objects.equals()
每个字段都应通过 Objects.equals(field1, field2) 比较。它内部自动处理 null,无需手动判空,也避免了 == 误用于字符串等引用类型。
立即学习“Java免费学习笔记(深入)”;
- 基本类型直接用
==(如int、boolean) - 引用类型(包括数组)统一用
Objects.equals();若字段是数组,用Arrays.equals() - 浮点数慎用
==,建议用Double.compare()或指定误差范围
别忘了同步重写 hashCode
只要重写了 equals,就必须重写 hashCode,否则违反契约:相等的对象必须有相同的哈希码。推荐用 Objects.hash(field1, field2, ...) 生成,字段顺序和 equals 中的比较顺序保持一致。
- 如果
equals用了 A、B、C 字段,hashCode也必须只基于这三个字段计算 - 不参与
equals判断的字段,绝不能出现在hashCode中

















