WeiG's blog
首页
  • 类目

    • Java
    • Mysql
  • 学习笔记

    • 《SpringBoot-学习笔记》
  • 大杂烩
  • Docker
  • Git
  • 博客搭建
  • 程序人生
  • 所思所想
  • 人生游记
  • 归档
  • 分类
  • 标签
收藏
关于我

Wei-G

即使再小的帆也可以远航!
首页
  • 类目

    • Java
    • Mysql
  • 学习笔记

    • 《SpringBoot-学习笔记》
  • 大杂烩
  • Docker
  • Git
  • 博客搭建
  • 程序人生
  • 所思所想
  • 人生游记
  • 归档
  • 分类
  • 标签
收藏
关于我
  • Java

    • 线程池的线程复用原理
    • 一次线上线程池任务事故
    • 分布式事务小结
    • 为什么重写equals一定要重写hashcode
    • 注解Data与EqualsAndHashCode的使用
      • 前言
      • 场景
      • 分析
      • 补充
      • 总结
    • java泛型的理解
  • Mysql

  • 学习笔记

  • 后端乱炖
  • Java
gangzi
2022-01-19
时间 3分钟

注解Data与EqualsAndHashCode的使用

# 前言

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

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

为什么重写equals一定要重写hashcode (opens new window)

# 场景

在比较两个类的时候,如果多个类有相同的部分属性,把它们定义到父类中,恰好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上,有人提出这个问题:这里 (opens new window)

解决办法就是通过设置 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>
1
2
3
4
5
6
7
8

新建lombok.config文件

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

# 总结

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

参考 https://blog.csdn.net/feinifi/article/details/85275280 (opens new window)

https://www.cnblogs.com/lwcode6/p/12970582.html (opens new window)

https://www.cnblogs.com/binyue-sunmk/p/12632037.html (opens new window)

https://www.freesion.com/article/69941080555/ (opens new window)

#注解
上次更新: 2022/04/02, 11:19:25
为什么重写equals一定要重写hashcode
java泛型的理解

← 为什么重写equals一定要重写hashcode java泛型的理解→

本站总访问量 次 | 本站访客数 人
Copyright © 2021-2022 Gang zi | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 生命绿
  • 收获黄
  • 天空蓝
  • 激情红
  • 高贵紫