覆盖equals时请遵守通用约定
何时需要覆盖 equals 方法?
在 Java 中,默认的 equals 方法(继承自 Object 类)比较的是对象的内存地址(即 == 的行为)。但在以下场景中,需要覆盖 equals 以实现基于对象内容的逻辑相等性判断:
- 需要基于字段值判断对象相等性
场景:当两个对象的关键字段(如 ID、名称等)值相同时,应视为逻辑上的“相等”,即使它们是不同的对象实例。 - 对象将作为集合元素使用
场景:当对象被添加到 Set、用作 Map 的键,或需要调用 List.contains() 时,必须正确实现 equals 和 hashCode,否则集合无法正确识别相等对象。
举个例子 🌰
Set<Person> personSet = new HashSet<>();
Person p1 = new Person("007", "Abc");
Person p2 = new Person("007", "Abc");
personSet.add(p1);
System.out.println(personSet.contains(p2)); // 若未覆盖 equals,返回 false;覆盖后返回 true
- 需要自定义相等性规则
场景:当业务逻辑需要比较对象内容而非内存地址时
不需要覆盖 equals 的情况
- 类的每个实例本质上是唯一的
如 Thread、Enum 类型,Object 的默认实现已足够 - 父类已提供合适的equals实现
如大多数 List 实现继承自 AbstractList
覆盖 equals 方法遵守五大通用约定
- 自反性:任何非null对象必须等于自身
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
x.equals(null) 必须返回 false
覆盖 equals 的强制要求
覆盖了 equals(),必须同时覆盖 hashCode()
若 x.equals(y) 返回 true,则 x.hashCode() 必须等于 y.hashCode()。
违反此规则会导致对象在哈希集合(如 HashSet, HashMap)中行为异常。
始终要覆盖toStrng
重写 toString() 方法的目的是为对象提供清晰、可读的字符串表示。
场景
- 在字符串拼接:String s = "Person: " + person;
- 日志输出:log.info("User: {}", person);
- 直接输出对象信息:System.out.println(person);
以上会隐式调用toString() 方法
参考《Effective Java》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。