注解@Data与@EqualsAndHashCode的爱恨情仇

前言

@Data相当于

  • @Getter
  • @Setter
  • @RequiredArgsConstructor
  • @ToString
  • @EqualsAndHashCode

这5个注解的合集。所以可知,当使用@Data注解时,则有了@EqualsAndHashCode注解,那么编译后就会自动重写equals() 和 hashCode()方法。用在一般的普通实体类不会出现什么问题,但是当用来派生类上时,可能会导致不必要的错误。

首先明白一个问题“为什么要重写hashcode和equals方法?

为什么重写equals一定要重写hashcode

场景

在比较两个类的时候,如果多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中。

定义一个公共父类BaseEntity
image.png
定义一个派生子类User
image.png
此时发现@Data注解处出现警告
image.png
大致意思是默认重写生成子类的equals和hashCode方法,不会包含或者考虑父类的属性。如果这是我们想要的操作,建议加上@EqualsAndHashCode(callSuper = false)注解。

也就是说,@Data注解在派生子类上时默认@EqualsAndHashCode(callSuper = false),即重写子类的equals和hashcode不包含父类

添加注解@EqualsAndHashCode(callSuper = false),报警消失
image.png
进行测试
image.png
结果:true,true

当更改注解为@EqualsAndHashCode(callSuper = true)时,进行测试,结果:false,false

经过上述讲解,出现这个结果毫不吃惊,因为字段id,IdentityNo是父类的属性

分析

当@Data注解在派生子类User上时,默认等同于@EqualsAndHashCode(callSuper = false)

通过反编译工具查看项目target/classes目录下的User.class的equals和hashcode方法,默认情况下属性都是使用的他自身的属性。
image.png
image.png

@EqualsAndHashCode(callSuper = true)

反编译工具查看User.class的equals和hashcode方法
image.png
image.png

补充

每一个继承的类,都需要这么来解决,也不是很方便。在stackoverflow上,有人提出这个问题:这里

解决办法就是通过设置 lombok 全局属性,在src/main/java 目录下创建 lombok.config 文件来解决

⚠️ 注:一定要在src/main/java 目录下创建才有效

配置pom.xml添加插件依赖

<plugin>
  	<groupId>org.apache.maven.plugins</groupId>
  	<artifactId>maven-compiler-plugin</artifactId>
  	<configuration>
  		<source>1.8</source>
  		<target>1.8</target>
  	</configuration>
</plugin>

新建lombok.config文件

# 声明该配置文件是一个根配置文件,从该配置文件所在的目录开始扫描
config.stopBubbling=true
# 全局配置 equalsAndHashCode 的 callSuper 属性为true
lombok.equalsAndHashCode.callSuper=call

总结

  1. 如果比较两个对象时需要考虑父类(基类,超类)中的成员,使用@EqualsAndHashCode(callSuper=true),才能正确比较
  2. 如果只是想在当前类比较字段,使用@EqualsAndHashCode(callSuper=false),或者不使用,它是默认选项
  3. 如果全部要比较 或 全部不需要比较 父类成员,使用全局配置 lombok.config

参考
https://blog.csdn.net/feinifi/article/details/85275280

https://www.cnblogs.com/lwcode6/p/12970582.html

https://www.cnblogs.com/binyue-sunmk/p/12632037.html

https://www.freesion.com/article/69941080555/

个人博客:wgzz.top
个人公众号:程序员WeiG
欢迎关注👏

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要让@Data排除掉@EqualsAndHashCode注解,有两种方法可以解决这个问题。第一种方法是使用@Getter、@Setter和@ToString注解代替@Data注解,并自定义equals(Object other)和hashCode()方法。在自定义equals(Object other)和hashCode()方法时,你可以根据需要选择只判断主键id是否相等即可,而不需要使用父类的属性。这样就可以排除掉@EqualsAndHashCode注解。 另一种方法是在使用@Data注解时同时加上@EqualsAndHashCode(callSuper=true)注解。通过官方文档我们可以得知,当使用@Data注解时,会生成默认的equals(Object other)和hashCode()方法,并且不会使用父类的属性。然而,当加上@EqualsAndHashCode(callSuper=true)注解后,就会包括父类的属性在内。所以,通过在@Data注解中加上@EqualsAndHashCode(callSuper=true)注解,也可以实现排除掉@EqualsAndHashCode注解的效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [lombok @Data @EqualsAndHashCode](https://blog.csdn.net/weixin_44766712/article/details/116309428)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [@EqualsAndHashCode() 和@Data注解的关系](https://blog.csdn.net/aiwaston/article/details/104722283)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值