正确重写equals和hashCode需遵循自反性、对称性、传递性、一致性和非null性;equals比较时用getClass()和Objects.equals避免类型和null问题,hashCode使用Objects.hash()保证相等对象有相同哈希值,且不依赖可变字段,防止集合中出现查找失败或性能下降。

在Java中正确重写equals和hashCode方法是保证对象在集合类(如HashMap、HashSet)中正常工作的关键。这两个方法都继承自Object类,如果未正确重写,可能导致逻辑错误或性能问题。
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。 -
一致性:只要对象没有被修改,多次调用
equals应返回相同结果。 -
非null性:对任何非null对象x,
x.equals(null)必须返回false。
重写示例:
public class Person {private String name;
private int age;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age &&
Objects.equals(name, person.name);
}
}
hashCode方法的重写规则
hashCode方法用于生成对象的哈希码,在使用HashMap、HashSet等结构时至关重要。必须遵守以下原则:
立即学习“Java免费学习笔记(深入)”;
- 在程序运行期间,只要对象用于
equals比较的字段未改变,hashCode应返回相同的整数。 - 如果两个对象通过
equals判断相等,那么它们的hashCode必须相同。 - 如果两个对象不相等,
hashCode可以不同,但尽量让其分布均匀以提升性能。
重写示例:
@Overridepublic int hashCode() {
return Objects.hash(name, age);
}
使用Objects.hash()是一种简洁且安全的方式,它会为多个字段生成组合哈希值。
常见错误与建议
- 只重写
equals而不重写hashCode:这会导致对象在HashMap中无法正确查找。 - 使用可变字段作为
equals或hashCode的依据:若对象存入HashSet后字段被修改,可能导致无法访问该对象。 - 比较字段时未处理null值:建议使用
Objects.equals(a, b),它能安全处理null。 - 误用
instanceof进行类型检查:应使用getClass()比较,避免破坏对称性或传递性(除非是final类)。
基本上就这些。只要遵循规范,并使用IDE或工具(如Lombok)自动生成,就能避免大部分问题。










