前言
派生类中@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,转载请注明出处。