前言

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:https://www.captainbed.cn/z


文章目录
以下是专栏第一篇的完整文章内容,按照要求包含错误场景复现、原理分析、修复方案和代码对比:
== 与 equals 的陷阱:对象比较为何总出错?
1. 错误场景复现
场景1:字符串比较的迷惑行为
String s1 = "Java";
String s2 = new String("Java");
String s3 = s2;
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
System.out.println(s2 == s3); // true
初级开发者常误用 == 比较字符串内容,而实际上 == 比较的是对象内存地址,而非字符串值。
场景2:自定义对象比较失效
class User {
private Long id;
private String name;
// 未重写 equals() 方法
}
User user1 = new User(1L, "Alice");
User user2 = new User(1L, "Alice");
System.out.println(user1.equals(user2)); // false(默认调用Object类的equals,等同于==)
即使两个对象业务逻辑上“相等”,未正确重写 equals() 方法仍会导致比较失败。
2. 原理解析
== 的本质
- 对基本类型(
int,double等):直接比较值是否相等 - 对引用类型(对象):比较堆内存地址是否相同(即是否为同一个对象)
equals() 的默认行为
Object类的默认实现:return (this == obj);- 若需按业务规则比较对象,必须重写
equals()方法。
3. 正确解决方案
正确重写 equals() 的步骤
@Override
public boolean equals(Object o) {
// 1. 自反性:检查是否与自己比较
if (this == o) return true;
// 2. 类型检查:null和非同类对象直接返回false
if (o == null || getClass() != o.getClass()) return false;
// 3. 类型转换
User user = (User) o;
// 4. 按业务逻辑比较关键字段
return Objects.equals(id, user.id) &&
Objects.equals(name, user.name);
}
// 必须同时重写 hashCode()!
@Override
public int hashCode() {
return Objects.hash(id, name);
}
为什么必须重写 hashCode()?
- 哈希集合(如HashMap/HashSet)依赖此方法:若两个对象
equals()为true,但hashCode()不同,会导致集合行为异常。 - 示例:将两个“相等”对象存入
HashSet,会错误地存储为两个独立元素。
4. 工具与最佳实践
避免手写错误的技巧
- 使用IDE自动生成(IntelliJ:
Alt + Insert→equals() and hashCode()) - Lombok简化代码:添加
@EqualsAndHashCode注解自动生成 - Guava工具类:
Objects.equal(a, b)安全比较对象
Code Review检查清单
| 检查项 | 正确做法 |
|---|---|
比较对象是否使用 equals()? | 引用类型永远用 equals(),基本类型用 == |
重写 equals() 时是否重写 hashCode()? | 必须同时重写,否则破坏哈希集合契约 |
是否处理了 null 和类型检查? | 避免 ClassCastException 和 NullPointerException |
5. 真实案例
某电商平台因未重写 Order 类的 equals(),导致促销系统错误判断重复订单。
后果:用户利用漏洞重复领取优惠券,造成数十万元损失。
修复:重写 equals() 和 hashCode(),比较订单ID和用户ID字段。
总结
==是“物理相等”,equals()是“逻辑相等”- 重写
equals()必须同时重写hashCode() - 使用工具自动生成代码,避免低级错误
下期预告:《常见的空指针异常(NullPointerException)及预防方法》——如何用Optional和防御性编程让代码“坚如磐石”。
希望这篇内容能帮助初级开发者彻底理解对象比较的核心机制,建议结合代码实操加深记忆。
联系作者
职场经验分享,Java面试,简历修改,求职辅导尽在科技泡泡
思维导图面试视频合集


本文介绍了Apollo自动驾驶技术在测试中的应用,包括单元测试基础,如使用Jest或Mocha编写测试用例,以及集成测试指南,如模拟真实服务器端测试。强调了持续集成与自动化测试的重要性,以确保代码质量、稳定性并提高开发效率。
3492






