引言

今天中午正在带着耳机遨游在代码的世界里,被运营在群里@了,气冲冲的反问我最近有删生产的用户数据的吗?我肯定客气的回答道没有呀?生产的数据我怎么能随随便便可以删除,这可是公司的红线,再说了我也没有数据库的删除权限啊,不过查询权限还是有的。赶紧登上堡垒机,然后去生产数据库查一下数据,查了一下数据是还在的,吓死了,数据还在问题就不大了,无非就是应用程序出问题了,赶紧打开代码查看下,为什么会少了一条用户数据,看了下代码貌似没啥问题就是比较简单的一个逻辑,直接从DB通过分页查询数据给到前端,然后前端负责展示,没有啥复杂的逻辑。心想肯定是前端的问题,肯定是他少展示了数据,立马把问题也甩给了他,让他帮忙配合一起看看是否是前端的问题,然后自己也仔细看看代码,不到一分钟前端说他展示的数据没有问题,都是后端给到的,没有漏掉展示的。那就是后端的bug了罗。肉眼望去觉得可能出问题的就是分页导致的数据丢了。不过这个分页插件是全公司都在用,应该不至于出问题吧,找不到问题只能让测试帮忙在测试环境试试,看看是否可以复现。

测试环境复现

仔细看了一眼,居然有个去重的方法,去重逻辑也比较简单就是把list通过转为set去下重,看下来应该就是这个去重方法有问题了 大致写了单元测试模仿了下生产的数据,大致逻辑如下:

public static void main(String[] args) {Set<UserDTO> userSet = new HashSet<>();UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("java金融");UserDTO userDTO1 = new UserDTO();userDTO1.setId(2);userDTO1.setUserName("java金融");userSet.add(userDTO);userSet.add(userDTO1);System.out.println(userSet.size());System.out.println(userDTO1.equals(userDTO));}@Datastatic class UserDTO extends BaseDTO {private String userName;}@Datastatic class BaseDTO {private Integer id;}

我们可以输出结果set集合的长度是1,user1user2 是相等的,明明两个userID是不一样的,为何会相等,我们知道set可以去重 是因为Set的操作,都是通过操作map来实现的,setadd其实就是调用mapput方法,mapput方法我相信大家应该都去看过其源码,这里就不详细再说了,大概流程就是通过key通过hash算法定位到数组的下标,先判断keyhash是否相等,如果相等再去判断key的value相等,如果都相等就会覆盖原来的值。我们上面这个例子就是对象的hashvalue都相等导致,但是我们的两个对象user1user2 应该是不等的,因为ID不等,那为什么会相等列?我们仔细看下上面的代码,我们使用了lombok里面@Data注解,我们可以看看这个注解帮我们生成了哪些方法通过上面的对比我们可以看出@Data注解帮我们生成了 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法,这个注解确实比较方便。上面那个bug 就是因为它生成的equals方法有问题,我们可以把上述代码编译下,然后把class 里面生成的equals方法拷贝出来看看

通过上述生成的代码我们可以看出equals方法只比较了userName这个字段,也就是当前类的字段,并没有去比较父类的字段,这就是导致两个对象相等的原因,我们既然找到问题了,那解决问题就比较简单。

解决问题

  • 手动重写equalshashCode方法,这种方法肯定是不推荐的,我们既然用了lombok就是为了解放我们的双手,是代码变得更加简洁。

  • 在比较的类上加上@EqualsAndHashCode(callSuper = true) callSuper = true 会包含父类的equalshashCode方法 我们可以对比下加上@EqualsAndHashCode(callSuper = true)和没有加上这个注解生成的equals方法的代码差异。差异点还是很明显的,加入了@EqualsAndHashCode(callSuper = true) 会去调用父类的equals方法比较,所以这个注解也能够解决这个问题。

  • 这样加上注解确实可以解决问题,但是每个类上面都要加上这个注解,这也是个体力活。我们可以再找找其他的方案,例如有没有比如配置文件设置下什么的,然后就能全局生效了。最终通过查询资料发现我们我们写一个lombok.config的配置文件放在我们项目的根目录下面,内容写上lombok.equalsAndHashCode.callSuper = call效果等同于@EqualsAndHashCode(callSuper = true),这样的话我们就不需要为每个类都去加上这个注释了,相当于在这个项目下面只要用到了@Data注解的类都会为其加上@EqualsAndHashCode(callSuper = true)通过配置文件的方式就可以全局生效。

总结

  • 我们再来回顾下上面的问题,归根结底还是由于对象的equals方法使用不当引起的,所以我们在如果在判断自定义对象业务判断相等的时候需要去重写下hashCodeequals方法,重写的时候我们可以通过idea来生成,生成后最好还是去看一眼,看看生成的是否符合我们的业务要求。

  • 我们在工作中操作一些常见的容器类比如Set、Map等来实现一些我们自己的业务,我们还是有必要去看看它们的源码的,就比如我们通过Set来进行去重,如果我们是使用的自定义对象的话,如果没有重写hashCodeequals方法的话,去重就会去不成功,我们只有了解了它,才能真正的去用好它。在关于hashCodeequals 阿里巴巴开发手册也有明确的说到

  • lombok 用起来还是挺爽的,但是还是有一些细节需要稍微注意下。使用前可以大概的去看看它的官网提供的内容,不然出现莫名其妙的问题你都不知道如何下手。这个就有点类似于我们使用SpringBoot一样,用起来非常爽,但是如果遇到莫名其妙的bug解决起来就比较头疼。

  • 最后我们再来回顾几道关于hashCodeequals的比较常见的面试题?其实如果我们只要真正看过HashMap的源码的话,这下面几个面试题还是非常简单的。什么情况下需要我们去重写 方法?如果只重写equals方法不重写HashCode可以吗?equals ,== 和hashcode()的区别?

一不小心就踩了lombok的坑?相关推荐

  1. 编程坑太多,Map 集合怎么也有这么多坑?一不小心又踩了好几个!| 原力计划...

    作者 | 楼下小黑哥 头图 | CSDN下载自图虫 作为 List 集合好兄弟 Map,我们天天都在使用,一不小心就会踩坑. 今天我就来总结这些常见的坑,再捞自己一手,防止后续同学再继续踩坑. 本文设 ...

  2. 拼多多商家一定不要踩这几个坑,坑坑致命!

    大家好,我是面兜兜,关注面兜兜每天解锁不同的店铺运营知识!今天面兜兜给大家分享的是关于新手常见陷阱. 今天,在拼多多开店的商家可谓是日益增多,毕竟其本身的流量和购物模式就足够吸引商家目光,但每一个平台 ...

  3. 安装python爬虫scrapy踩过的那些坑和编程外的思考

    '转载地址:http://www.cnblogs.com/rwxwsblog/p/4557123.html' 这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬 ...

  4. Vue2.0配置mint-ui踩过的那些坑

    Vue2.0配置mint-ui踩过的那些坑 最近开发项目的时候逐渐采用vue.js+mint-ui的技术栈,但是昨天开始配置开发环境的时候,遇到了各种报错,即使是按照两家的官方文档配置,也还是会报错, ...

  5. 与webview打交道中踩过的那些坑

    随着HTML5被越来越多的用到web APP的开发当中,webview这一个神器便日渐凸显出重要地位.简要的说,webview能够在移动应用中开辟出一个窗口,在里面显示html页面,css以及js代码 ...

  6. charles都踩过哪些坑_开水果店的你,踩过了哪些坑?

    我们认为,开水果店遇到的大小问题,很多时候是有共性的.不论是开店新手还是老手,看看这里的案例,是否可以避免走一些弯路呢? 案例1 刘大飞第1次创业开水果踩过的那些坑.创业开水果店之前,刘大飞和合伙人一 ...

  7. 美团在Redis上踩过的一些坑-5.redis cluster遇到的一些问题

    转载请注明出处哈:http://carlosfu.iteye.com/blog/2254154 由于演讲时间有限,有关Redis-Cluster,演讲者没做太多介绍,简单的介绍了一些Redis-Clu ...

  8. python iocp_记对协程增加IOCP支持时候踩过的一些坑

    之前在对tbox的协程库中增加了基于IOCP的io处理,期间踩了不少的坑,这边就做个简单记录吧,省的到时候忘记了,自己看不懂自己这个代码 (= =) 坑点一 WSARecv/WSASend在lpNum ...

  9. Spring Cloud 升级最新 Finchley 版本,踩了所有的坑

    转载自   Spring Cloud 升级最新 Finchley 版本,踩了所有的坑 Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Bo ...

最新文章

  1. Oracle数据类型简介【转贴】
  2. VHDL实现打地鼠游戏设计
  3. J2EE实现发送邮件功能
  4. Linux shell脚本启动 停止 重启jar包
  5. 语音识别api_语音识别 api_免费语音识别api - 云+社区 - 腾讯云
  6. linux shell eval,【shell】bash shell 中 set 和 eval 命令的使用
  7. yolov3中如何进行聚类得到anchor box的
  8. 【Struts2】剖析Struts2中的反射技术 ValueStack(值栈)
  9. 【信息系统项目管理师】案例分析高频记忆考点汇总
  10. YOLOv5训练自己的数据集(超详细完整版)
  11. 机器学习(十)——支持向量机
  12. 除了花瓣、站酷,提高品位、汲取灵感,关注这10个国内优质设计网站
  13. elasticsearch的服务器响应异常及应对策略
  14. android网络编程案例,深入理解Android网络编程pdf 完整版
  15. 微信消息能在服务器上彻底清除,快速彻底删除微信消息的方法如此简单 很多人都用错了方法!...
  16. 聊聊被注销的TMQ公众号
  17. 汽车计算机控制系统及其组成,汽车计算机控制系统的研究.doc
  18. 宝塔一键安装wordpress
  19. 用python给小孩随机生成一组10以内加减法
  20. 扔掉代码表!用RNN“破解”摩斯电码

热门文章

  1. 单片机程序100-300例(付注释详解)
  2. 机械自动化专业转 PLC 还是单片机,路会更好走一些?
  3. 借助tkinter设计人脸检测的界面(摄像头检测,视频检测,视频检测并保存)
  4. poj3007(set的应用)
  5. 二叉搜索树c/c++代码实现
  6. HDU2196[树形dp+二次扫描]java和c++版本题解
  7. php ascii转native,编码转换工具native2ascii的使用
  8. 解题报告:Fake Maxpooling(单调队列求矩阵的和)
  9. 【动态规划专题】最长上升子序列模型
  10. ACM_模拟——数学问题