== 与 equals 的陷阱:对象比较为何总出错?

前言

请添加图片描述

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家: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. 工具与最佳实践

避免手写错误的技巧

  1. 使用IDE自动生成(IntelliJ: Alt + Insert → equals() and hashCode())
  2. Lombok简化代码:添加 @EqualsAndHashCode 注解自动生成
  3. 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面试,简历修改,求职辅导尽在科技泡泡
思维导图面试视频合集
在这里插入图片描述
在这里插入图片描述

Java BigDecimal比较:compareTo与equals的区别与实战避坑指南 在Java高精度数值计算领域,BigDecimal是处理金融、科学计算的核心类。其比较操作涉及数值大小与对象相等性的不同维度,理解compareTo与equals方法的本质区别是避免线上事故的关键。compareTo方法遵循Comparable接口契约,专注于纯数值的大小比较,忽略精度差异,是排序、范围校验等业务逻辑的黄金标准。而equals方法则严格比较数值和精度,用于需要区分精度的精确匹配场景,如HashMap键值对。误用equals进行数值等值判断是常见陷阱,可能导致金额核对、条件判断等核心业务逻辑出 阅读详情

相关推荐

Objects.equals有坑

前言 最近review别人代码的时候,发现有个同事,在某个业务场景下,使用Objects.equals方法判断两个值相等时,返回了跟预期不一致的结果,引起了我的兴趣。 原本以为判断结果会返回true的,但实际上返回了false。 记得很早之前,我使用Objects.equals方法也踩过类似的坑,所以有必要把这个问题记录下来,分享给大家。 到底怎么回事呢? 1. 案发现场 假设现在有这样一个需求:判断当前登录的用户,如果是我们指定的系统管理员,则发送一封邮件。系统管理员没有特殊的字段标识,他的用户id=88

4202

PDF资料:自动驾驶汽车软件单元测试.pdf

自动驾驶汽车软件单元测试

华为Atlas200DK实战指南:从零搭建AI开发环境到人像语义分割模型部署

本文提供了一份详尽的华为Atlas 200DK AI开发环境搭建与模型部署实战指南。文章采用合设环境方案,从SD卡准备、系统镜像烧录、网络配置到必备工具安装,逐步引导开发者完成环境搭建。核心部分详细讲解了如何利用华为ATC工具将TensorFlow模型转换为昇腾专用格式,并最终成功编译和运行人像语义分割模型,实现实时人像识别效果。

weixin_29309213的博客 356

海康工业相机LabVIEW二次开发实战——参数配置优化与图像高效存储

本文详细介绍了海康工业相机在LabVIEW平台上的二次开发实战,重点解析了相机参数配置的优化方法与图像高效存储策略。通过剖析曝光、增益、触发模式等核心参数的设置逻辑,并结合生产者-消费者设计模式,指导开发者构建稳定、高效的图像采集与异步存储流程,有效提升工业视觉项目的开发效率与系统稳定性。

weixin_29306317的博客 222

uniapp - 详细实现移动端公众号 H5 网页授权登录流程及示例代码,申请测试公众号全流程及本地调试无需部署上线服务器就能直接调起微信登陆授权页面,手机移动端h5公众号页面利用微登录拿到用户数据!

uni-app,微信公众号,h5网页,uniapp网页端,手机端H5公众号页面,微信网页登陆,uniApp详细实现公众号的登录,微信授权第三方网站登录,流程及逻辑详细教程,OAuth2.0,公众号网页授权,微信网页授权通过code换取网页授权,redirect_url,参数错误,解决,报错,无法调起,如何申请测试公众号,微信公众平台测试号的申请与使用,获取用户openid手机号昵称头像,利用测试号实现本地调试微信登录授权,本地无法调试怎么办,测试公众号,在开发环境下怎么测试,用项目本地ip地址,微信公众号平

🏆 前端领域优质创作者 5064

【异常】XXL-JOB提示异常ERROR com.xxl.job.core.util.XxlJobRemotingUtil - connect timed out

打开XXL-JOB的ELK,发现一堆报错。

奶爸的编程之路,也就一周冷个三天 2049

1篇2章1节:在 Mac 上安装 Python,从环境检查到工具配置的完整指南

Python 是当今最流行的高级编程语言之一,广泛应用于数据分析、人工智能、自动化脚本和 Web 开发。虽然 macOS 曾自带 Python,但从 macOS 12.3 开始,系统不再默认提供可直接使用的版本,因此需要手动安装。本文将详细讲解如何在 Mac 上安装最新版本的 Python,如何验证安装是否成功,以及如何配置 IDLE 和 Python Launcher 等工具,为日常开发和学习打下坚实基础。即便你是完全的新手,也能按步骤完成环境搭建。

MD Code 850

uniapp [全端兼容] - 详细实现拍照或相册选取图片后插入水印功能,手机拍照或相册上传图像并添加自定义水印及指定位置显示水印,uniApp给图片加水印后上传到后端服务器或保存到本机相册详细教程!

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,图片水印,上传照片带水印,从相册选择图片加水印功能,拍完照片给图片加水印,添加照片水印,uniapp图片加水印,为图片添加自定义水印,uni-app上传图片并添加水印,上传图片加水印,uni-app如何对拍摄的照片加水印,uni-app实现图片上传添加水印操作,给上传的图片添加上水印,图片加完水印后如何上传到服务器,水印相机,拍照图片加水印,相册选取后给图片加上水印,渲染失败,无法保存,文字水印,日期

🏆 前端领域优质创作者 1万+

一步一步教你如何安装IP-Guard(客户端WINDOWS篇)

1、安装完服务器后,在服务器右下角有一个IP-GUARD图标:如图 2、点图标右键选注册: 3、注册成功后, 4、在开始菜单里选生成客户端安装包。 5、生成客户端安装包成功,安装名字可以任意,但是最好是英文名字。 6、将客户端安装程序复制到桌面。 7、退出所有杀毒软件、安全卫士、电脑管家等然后运行 8、安装完成后,立即重启计算机。IPguard客户端安装完成。 9、这样在控制里就可以看到已经安装客户端的计算机,在线显示蓝色,灰色表示计算机已经离线货关机 ...

IP-Guard专栏 5631

Oracle数据库表空间使用情况查询

在Oracle数据库中,表空间(Tablespace)是用于存储表、索引和其他数据库对象的逻辑存储单元。了解表空间的使用情况对于数据库管理员和开发人员来说是非常重要的,因为它可以帮助他们监控数据库的空间使用情况并进行容量规划。本文将介绍如何查询Oracle数据库中的表空间使用情况。通过执行以上SQL查询语句,你可以获得Oracle数据库中表空间的使用情况、文件大小和表空间大小等信息。这些信息可以帮助你了解数据库的存储情况,并进行适当的优化和容量规划。查看表空间的数据文件和表空间大小。查看表空间的使用情况。

CsmbPascal的博客 860

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

上一篇: 资源泄漏危机:忘记关闭的IO流与数据库连接
下一篇: String拼接的代价:为何StringBuilder是救星?
雪碧有白泡泡
雪碧有白泡泡 优质创作者: 编程框架技术领域 优质创作者: 编程框架技术领域
博客等级 码龄5年 1万+粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪碧有白泡泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值