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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

请添加图片描述

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家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 + Insertequals() and hashCode()
  2. Lombok简化代码:添加 @EqualsAndHashCode 注解自动生成
  3. Guava工具类Objects.equal(a, b) 安全比较对象

Code Review检查清单

检查项正确做法
比较对象是否使用 equals()引用类型永远用 equals(),基本类型用 ==
重写 equals() 时是否重写 hashCode()必须同时重写,否则破坏哈希集合契约
是否处理了 null 和类型检查?避免 ClassCastExceptionNullPointerException

5. 真实案例

某电商平台因未重写 Order 类的 equals(),导致促销系统错误判断重复订单。
后果:用户利用漏洞重复领取优惠券,造成数十万元损失。
修复:重写 equals()hashCode(),比较订单ID和用户ID字段。


总结

  • == 是“物理相等”,equals() 是“逻辑相等”
  • 重写 equals() 必须同时重写 hashCode()
  • 使用工具自动生成代码,避免低级错误

下期预告:《常见的空指针异常(NullPointerException)及预防方法》——如何用Optional和防御性编程让代码“坚如磐石”。


希望这篇内容能帮助初级开发者彻底理解对象比较的核心机制,建议结合代码实操加深记忆。

联系作者

职场经验分享,Java面试,简历修改,求职辅导尽在科技泡泡
思维导图面试视频合集
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

雪碧有白泡泡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值