自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一不小心就踩了Lombok的坑?

開(kāi)發(fā) 前端
今天中午正在帶著耳機(jī)遨游在代碼的世界里,被運(yùn)營(yíng)在群里@了,氣沖沖的反問(wèn)我最近有刪生產(chǎn)的用戶數(shù)據(jù)的嗎?我肯定客氣的回答道沒(méi)有呀?生產(chǎn)的數(shù)據(jù)我怎么能隨隨便便可以刪除,這可是公司的紅線,再說(shuō)了我也沒(méi)有數(shù)據(jù)庫(kù)的刪除權(quán)限啊,不過(guò)查詢權(quán)限還是有的。

 [[413622]]

引言

今天中午正在帶著耳機(jī)遨游在代碼的世界里,被運(yùn)營(yíng)在群里@了,氣沖沖的反問(wèn)我最近有刪生產(chǎn)的用戶數(shù)據(jù)的嗎?我肯定客氣的回答道沒(méi)有呀?生產(chǎn)的數(shù)據(jù)我怎么能隨隨便便可以刪除,這可是公司的紅線,再說(shuō)了我也沒(méi)有數(shù)據(jù)庫(kù)的刪除權(quán)限啊,不過(guò)查詢權(quán)限還是有的。趕緊登上堡壘機(jī),然后去生產(chǎn)數(shù)據(jù)庫(kù)查一下數(shù)據(jù),查了一下數(shù)據(jù)是還在的,嚇?biāo)懒?,?shù)據(jù)還在問(wèn)題就不大了,無(wú)非就是應(yīng)用程序出問(wèn)題了,趕緊打開(kāi)代碼查看下,為什么會(huì)少了一條用戶數(shù)據(jù),看了下代碼貌似沒(méi)啥問(wèn)題就是比較簡(jiǎn)單的一個(gè)邏輯,直接從DB通過(guò)分頁(yè)查詢數(shù)據(jù)給到前端,然后前端負(fù)責(zé)展示,沒(méi)有啥復(fù)雜的邏輯。心想肯定是前端的問(wèn)題,肯定是他少展示了數(shù)據(jù),立馬把問(wèn)題也甩給了他,讓他幫忙配合一起看看是否是前端的問(wèn)題,然后自己也仔細(xì)看看代碼,不到一分鐘前端說(shuō)他展示的數(shù)據(jù)沒(méi)有問(wèn)題,都是后端給到的,沒(méi)有漏掉展示的。那就是后端的bug了羅。肉眼望去覺(jué)得可能出問(wèn)題的就是分頁(yè)導(dǎo)致的數(shù)據(jù)丟了。不過(guò)這個(gè)分頁(yè)插件是全公司都在用,應(yīng)該不至于出問(wèn)題吧,找不到問(wèn)題只能讓測(cè)試幫忙在測(cè)試環(huán)境試試,看看是否可以復(fù)現(xiàn)。

測(cè)試環(huán)境復(fù)現(xiàn)

仔細(xì)看了一眼,居然有個(gè)去重的方法,去重邏輯也比較簡(jiǎn)單就是把list通過(guò)轉(zhuǎn)為set去下重,看下來(lái)應(yīng)該就是這個(gè)去重方法有問(wèn)題了 大致寫了單元測(cè)試模仿了下生產(chǎn)的數(shù)據(jù),大致邏輯如下:

  1. public static void main(String[] args) { 
  2.         Set<UserDTO> userSet = new HashSet<>(); 
  3.         UserDTO userDTO = new UserDTO(); 
  4.         userDTO.setId(1); 
  5.         userDTO.setUserName("java金融"); 
  6.  
  7.         UserDTO userDTO1 = new UserDTO(); 
  8.         userDTO1.setId(2); 
  9.         userDTO1.setUserName("java金融"); 
  10.         userSet.add(userDTO); 
  11.         userSet.add(userDTO1); 
  12.         System.out.println(userSet.size()); 
  13.         System.out.println(userDTO1.equals(userDTO)); 
  14.     } 
  15.  
  16.     @Data 
  17.     static class UserDTO extends BaseDTO { 
  18.         private String userName; 
  19.     } 
  20.     @Data 
  21.     static class BaseDTO { 
  22.         private Integer id; 
  23.     } 

我們可以輸出結(jié)果set集合的長(zhǎng)度是1,user1和user2 是相等的,明明兩個(gè)user的ID是不一樣的,為何會(huì)相等,我們知道set可以去重 是因?yàn)镾et的操作,都是通過(guò)操作map來(lái)實(shí)現(xiàn)的,set的add其實(shí)就是調(diào)用map的put方法,map的put方法我相信大家應(yīng)該都去看過(guò)其源碼,這里就不詳細(xì)再說(shuō)了,大概流程就是通過(guò)key通過(guò)hash算法定位到數(shù)組的下標(biāo),先判斷key的hash是否相等,如果相等再去判斷key的value相等,如果都相等就會(huì)覆蓋原來(lái)的值。我們上面這個(gè)例子就是對(duì)象的hash和value都相等導(dǎo)致,但是我們的兩個(gè)對(duì)象user1和user2 應(yīng)該是不等的,因?yàn)镮D不等,那為什么會(huì)相等列?我們仔細(xì)看下上面的代碼,我們使用了lombok里面@Data注解,我們可以看看這個(gè)注解幫我們生成了哪些方法

通過(guò)上面的對(duì)比我們可以看出@Data注解幫我們生成了 注在類上,提供類的get、set、equals、hashCode、canEqual、toString方法,這個(gè)注解確實(shí)比較方便。上面那個(gè)bug 就是因?yàn)樗傻膃quals方法有問(wèn)題,我們可以把上述代碼編譯下,然后把class 里面生成的equals方法拷貝出來(lái)看看

通過(guò)上述生成的代碼我們可以看出equals方法只比較了userName這個(gè)字段,也就是當(dāng)前類的字段,并沒(méi)有去比較父類的字段,這就是導(dǎo)致兩個(gè)對(duì)象相等的原因,我們既然找到問(wèn)題了,那解決問(wèn)題就比較簡(jiǎn)單。

解決問(wèn)題

  • 手動(dòng)重寫equals和hashCode方法,這種方法肯定是不推薦的,我們既然用了lombok就是為了解放我們的雙手,是代碼變得更加簡(jiǎn)潔。
  • 在比較的類上加上@EqualsAndHashCode(callSuper = true) callSuper = true 會(huì)包含父類的equals 和 hashCode方法 我們可以對(duì)比下加上@EqualsAndHashCode(callSuper = true)和沒(méi)有加上這個(gè)注解生成的equals方法的代碼差異。

圖片差異點(diǎn)還是很明顯的,加入了@EqualsAndHashCode(callSuper = true) 會(huì)去調(diào)用父類的equals方法比較,所以這個(gè)注解也能夠解決這個(gè)問(wèn)題。

  • 這樣加上注解確實(shí)可以解決問(wèn)題,但是每個(gè)類上面都要加上這個(gè)注解,這也是個(gè)體力活。我們可以再找找其他的方案,例如有沒(méi)有比如配置文件設(shè)置下什么的,然后就能全局生效了。最終通過(guò)查詢資料發(fā)現(xiàn)我們我們寫一個(gè)lombok.config的配置文件放在我們項(xiàng)目的根目錄下面,內(nèi)容寫上lombok.equalsAndHashCode.callSuper = call效果等同于@EqualsAndHashCode(callSuper = true),這樣的話我們就不需要為每個(gè)類都去加上這個(gè)注釋了,相當(dāng)于在這個(gè)項(xiàng)目下面只要用到了@Data注解的類都會(huì)為其加上@EqualsAndHashCode(callSuper = true)通過(guò)配置文件的方式就可以全局生效。

總結(jié)

  • 我們?cè)賮?lái)回顧下上面的問(wèn)題,歸根結(jié)底還是由于對(duì)象的equals方法使用不當(dāng)引起的,所以我們?cè)谌绻谂袛嘧远x對(duì)象業(yè)務(wù)判斷相等的時(shí)候需要去重寫下hashCode和equals方法,重寫的時(shí)候我們可以通過(guò)idea來(lái)生成,生成后最好還是去看一眼,看看生成的是否符合我們的業(yè)務(wù)要求。
  • 我們?cè)诠ぷ髦胁僮饕恍┏R?jiàn)的容器類比如Set、Map等來(lái)實(shí)現(xiàn)一些我們自己的業(yè)務(wù),我們還是有必要去看看它們的源碼的,就比如我們通過(guò)Set來(lái)進(jìn)行去重,如果我們是使用的自定義對(duì)象的話,如果沒(méi)有重寫hashCode和equals方法的話,去重就會(huì)去不成功,我們只有了解了它,才能真正的去用好它。在關(guān)于hashCode和equals 阿里巴巴開(kāi)發(fā)手冊(cè)也有明確的說(shuō)到

  • lombok 用起來(lái)還是挺爽的,但是還是有一些細(xì)節(jié)需要稍微注意下。使用前可以大概的去看看它的官網(wǎng)提供的內(nèi)容,不然出現(xiàn)莫名其妙的問(wèn)題你都不知道如何下手。這個(gè)就有點(diǎn)類似于我們使用SpringBoot一樣,用起來(lái)非常爽,但是如果遇到莫名其妙的bug解決起來(lái)就比較頭疼。
  • 最后我們?cè)賮?lái)回顧幾道關(guān)于hashCode和equals的比較常見(jiàn)的面試題?其實(shí)如果我們只要真正看過(guò)HashMap的源碼的話,這下面幾個(gè)面試題還是非常簡(jiǎn)單的。什么情況下需要我們?nèi)ブ貙? 方法?如果只重寫equals方法不重寫HashCode可以嗎?equals ,== 和hashcode()的區(qū)別?

本文轉(zhuǎn)載自微信公眾號(hào)「 java金融」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 java金融公眾號(hào)。

 

 

責(zé)任編輯:武曉燕 來(lái)源: java金融
相關(guān)推薦

2023-03-10 08:27:07

for循環(huán)項(xiàng)目線性結(jié)構(gòu)

2021-01-05 22:49:37

Python編程語(yǔ)言Java

2020-10-28 15:07:01

Arthas

2020-10-26 08:56:32

技術(shù)總監(jiān)程序員

2025-03-05 00:27:00

2021-04-30 08:21:22

Linux管道設(shè)計(jì)

2021-03-29 18:47:53

APP服務(wù)端通信安全數(shù)據(jù)安全

2021-10-07 16:45:06

MySQL數(shù)據(jù)庫(kù)

2024-05-13 07:58:52

開(kāi)源項(xiàng)目PR

2018-01-18 22:26:30

2021-01-30 09:50:54

MySQL密碼服務(wù)器

2019-09-19 20:47:29

刷臉支付人臉識(shí)別人工智能

2020-09-29 07:44:20

跨域前后端分離插件

2021-01-08 09:36:23

程序員比特幣黑客

2021-03-26 06:14:26

Hashcode項(xiàng)目排查

2020-04-30 09:45:41

安卓App小米

2022-09-27 18:19:32

Java數(shù)據(jù)結(jié)構(gòu)

2019-07-29 14:38:35

服務(wù)器開(kāi)發(fā)工具

2021-05-11 16:20:02

網(wǎng)站HTTPHTTPS

2020-02-03 09:10:23

數(shù)據(jù)庫(kù)刪庫(kù)刪庫(kù)跑路
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)