当前位置: 首页 > article >正文

读《Effective Java》笔记 - 条目10

条目10:在重写equals方法时要遵守通用约定

为什么需要重写 equals 方法?

  • 对象比较的需求: 默认情况下,Object 类的 equals 方法是通过对象引用进行比较的,即只有当两个对象是同一个实例时才返回 true。这对于逻辑上“值相等”的比较(value equality)是不够的。例如,String 类重写了 equals 方法,比较的是字符串内容而不是引用。
  • 需要自定义比较逻辑: 在某些情况下,类需要基于特定的属性定义两个对象的相等性。例如,在一个 Person 类中,可以通过 nameid 来判断两个 Person 对象是否相等。

通用约定

  1. 自反性(Reflexive)
    • 对于任何非空引用值 xx.equals(x) 必须返回 true
  2. 对称性(Symmetric)
    • 对于任何非空引用值 xy,如果 x.equals(y) 返回 true,那么 y.equals(x) 也必须返回 true
  3. 传递性(Transitive)
    • 对于任何非空引用值 xyz,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 必须返回 true
  4. 一致性(Consistent)
    • 对于任何非空引用值 xy,在对象未被修改的情况下,多次调用 x.equals(y) 必须始终返回相同的结果。
  5. 非空性(Non-nullity)
    • 对于任何非空引用值 xx.equals(null) 必须返回 false

正确重写equals 方法

  1. 使用 == 检查“自反性”

    if (this == obj) return true;
    
  2. 使用 instanceof 检查类型

    if (!(obj instanceof MyClass)) return false;
    
  3. 比较关键字段

    MyClass other = (MyClass) obj; // 类型转换
    return field1.equals(other.field1) && field2 == other.field2;
    
  4. 考虑性能和空值

    对可能为 null 的字段,使用 Objects.equals 或提前检查:

    Objects.equals(field1, other.field1)
    

完整代码

import java.util.Objects;

public class Person {
    private final String name;
    private final int id;

    public Person(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        // 自反性检查
        if (this == obj) return true;

        // 类型检查
        if (!(obj instanceof Person)) return false;

        // 强制转换后比较字段
        Person other = (Person) obj;
        return id == other.id && Objects.equals(name, other.name);
    }

    @Override
    public int hashCode() {
        // 始终与 equals 一致
        return Objects.hash(name, id);
    }
}

需要注意:

  1. 如果重写了 equals,也必须重写 hashCode,否则会违反 hashCode 的契约规则,导致在集合(如 HashMapHashSet)中行为异常。
  2. 不要在 equals 方法中比较不会影响逻辑相等性的字段,如缓存值或计算中间结果。
  3. 如果一个对象的字段参与了 equals 的比较逻辑,建议该字段是不可变的(final),以避免修改后违反一致性。
  4. 如果类实现了 Comparable 接口,那么 equals 的定义应该与 compareTo 保持一致,即 x.compareTo(y) == 0 时,x.equals(y) 必须返回 true

违法约定的风险

  1. 在集合中的行为异常。 如果 equalshashCode 不一致,可能导致 HashMapHashSet 无法正确存取数据。
  2. 不符合用户预期。如果 equals 实现不符合通用约定,可能在业务逻辑中引入难以发现的错误。

自动工具

  • 可以使用一些注解自动生成equals等方法。如lombok
  • 使用IDEA快速生成

http://www.kler.cn/a/413733.html

相关文章:

  • Maven 依赖项配置
  • 人工智能如何改变你的生活?
  • 面试手撕题积累
  • Long类型实体对象返给前端精度丢失问题
  • open-instruct框架使用记录:只使用huggingface数据集的小部分进行训练,如何修改dataset_info.json文件
  • 区块链:波场-TRON链
  • 化工行业 FMEA 与安全生产的关系
  • Java使用反射记录操作日志
  • 23省赛区块链应用与维护(房屋租凭【下】)
  • json object转x-www-form-urlencoded
  • ShuffleNet V2:高效卷积神经网络架构设计的实用指南
  • 计算机视觉中的距离变换:经典案例与Python代码解析
  • 无人机产业发展如何?如何进行产业分析?
  • 视觉感知与处理:解密计算机视觉的未来
  • MySQL子查询介绍和where后的标量子查询
  • yarn 任务 beyond the ‘PHYSICAL‘ memory limit 报错处理
  • 半导体、晶体管、集成电路、芯片、CPU、单片机、单片机最小系统、单片机开发板-概念串联辨析
  • 【网络安全设备系列】12、态势感知
  • Z2400023基于Java+Servlet+jsp+mysql的酒店管理系统的设计与实现 源码 调试 文档
  • 在Manjaro Gnome桌面的基础上安装Budgie桌面环境
  • 【入门篇】小游戏——多语言求解版
  • 希尔排序:一个“跳房子游戏”
  • 前端新手教程:HTML、CSS 和 JavaScript 全面详解及实用案例
  • 大数据新视界 -- Hive 数据分区:精细化管理的艺术与实践(上)(7/ 30)
  • 如何在 Ubuntu 22.04 上安装 Metabase 数据可视化分析工具
  • ssm194线上学习网站+vue(论文+源码)_kaic