前言
派生类中@EqualsAndHashCode注解使用的注意事项。
其实就是派生类什么时候需要显示指定@EqualsAndHashCode(callSuper = true)的问题。
重写equals要重写hashCode
在 Java 中,hashCode() 方法用于计算对象的哈希码,而哈希码在散列数据结构中用于确定对象的存储位置。当使用散列数据结构存储对象时,首先会根据对象的哈希码来确定存储位置,然后使用 equals() 方法来检查是否有碰撞(即两个不同的对象有相同的哈希码)。如果 hashCode() 和 equals() 方法不一致,可能会导致以下问题:
在散列数据结构中查找对象时,可能无法找到预期的对象,因为
hashCode()不同导致对象存储在不同的位置。当使用对象作为键(key)存储在
HashMap或Hashtable中时,由于哈希码不一致,可能无法正确地查找或删除对应的值(value)。在使用
HashSet存储对象时,可能会允许重复的对象进入集合,因为HashSet使用哈希码来检查对象是否已经存在,而哈希码不同意味着对象不同,即使它们的equals()方法返回true。
为了避免这些问题,在重写 equals() 方法时同时重写 hashCode() 方法,并且要确保两个方法在比较对象是否相等时一致。在重写 hashCode() 方法时,应该确保相等的对象返回相同的哈希码,这样可以保证对象在散列数据结构中能够正确存储和检索。
@EqualsAndHashCode注解的callSuper属性
@EqualsAndHashCode 是 Lombok 注解中的一个,用于自动生成 equals() 和 hashCode() 方法。其中,callSuper 属性是一个布尔值,用于指定是否在生成的 equals() 和 hashCode() 方法中调用父类的对应方法。
默认情况下,callSuper 属性的值为 false,即不调用父类的 equals() 和 hashCode() 方法。这意味着如果一个类继承自另一个类并使用 @EqualsAndHashCode 注解来生成方法,它只会考虑自己的成员变量,不考虑从父类继承的成员变量。
当 callSuper 属性的值为 true 时,Lombok 会在生成的 equals() 和 hashCode() 方法中调用父类的对应方法。这样做可以确保在比较两个对象是否相等时,除了考虑子类自己的成员变量外,还会考虑父类的成员变量。这对于包含继承关系的类结构是很有用的,因为它保证了在比较对象时考虑了所有继承链上的成员变量。
派生类需要显示指定@EqualsAndHashCode(callSuper = true)
现在来解释为什么在派生类上已经有 @Data 注解时,仍然需要加入 @EqualsAndHashCode(callSuper = true) 注解:
如果在派生类上仅使用
@Data注解而没有@EqualsAndHashCode注解,那么生成的equals()和hashCode()方法只会考虑派生类自己的成员变量,而不会考虑从父类继承的成员变量。这可能会导致在比较对象时忽略了所包含的父类属性,从而出现错误的结果。如果在派生类上同时使用
@Data和@EqualsAndHashCode(callSuper = true)注解,那么生成的equals()和hashCode()方法会考虑派生类自己的成员变量,同时也会调用父类的对应方法,确保了继承链上所有成员变量都会被考虑在内。
综上,当派生类需要考虑继承自父类的成员变量时,应该在派生类上使用 @EqualsAndHashCode(callSuper = true) 注解。而如果派生类只需要考虑自己的成员变量,不涉及继承关系,那么可以仅使用 @Data 注解而不添加 @EqualsAndHashCode 注解。
Lombok全局配置callSuper
在 Lombok 中,全局配置 callSuper 属性可以通过使用配置文件或在注解处理器的命令行参数中设置。这样可以为整个项目中的所有类统一配置 callSuper 属性的默认值。
在项目中配置 Lombok 的全局属性有以下两种方法:
- 使用
lombok.config文件:
在项目的根目录(通常可以放在src/main/java下)下创建一个名为 lombok.config 的文件,并在该文件中添加以下内容:
1 | # 声明该配置文件是一个根配置文件,从该配置文件所在的目录开始扫描 |
这样,所有使用 @EqualsAndHashCode 注解的类都会自动设置 callSuper 属性为 true,即在生成的 equals() 和 hashCode() 方法中调用父类的对应方法。
- 使用注解处理器的命令行参数:
在构建工具中配置注解处理器的命令行参数,将 lombok.equalsAndHashCode.callSuper 设置为 true。具体方法根据使用的构建工具有所不同:
- 对于 Maven,可以在
pom.xml文件中添加以下配置:
1 | <build> |
注意替换 ${lombok.version} 为你使用的 Lombok 版本。
- 对于 Gradle,可以在
build.gradle文件中添加以下配置(不一定对):
1 | dependencies { |
注意替换 lombokVersion 为你使用的 Lombok 版本。
参考
[1] https://zhuanlan.zhihu.com/p/460297314
后记
首发于 silencezheng.top,转载请注明出处。