使用lombok的@Data會(huì)導(dǎo)致棧溢出StackOverflowError問題
最近擼代碼發(fā)現(xiàn)一個(gè)問題,使用lombok的@Data會(huì)導(dǎo)致棧溢出StackOverflowError。
問題復(fù)現(xiàn)
兩個(gè)類,有循環(huán)引用:
@Data
public class Obj1 {
private String a;
private String b;
private Obj2 obj2;
}
@Data
public class Obj2 {
private String a;
private String b;
private Obj1 obj1;
}
public class Test {
public static void main(String[] args) {
Obj1 obj1 = new Obj1();
Obj2 obj2 = new Obj2();
obj1.setObj2(obj2);
obj2.setObj1(obj1);
System.out.println(obj1);
}
}執(zhí)行上述程序,結(jié)果出現(xiàn)棧溢出:

原因分析
首先出現(xiàn)上述問題的場(chǎng)景是出現(xiàn)了循環(huán)依賴。
@Data注解在什么情況下可能導(dǎo)致StackOverflowError情況呢?原因在于@Data重寫了hashCode()方法。
我們看一下兩個(gè)類的hashCode方法:
Obj1的hashCode方法
public int hashCode() {
int PRIME = true;
int result = 1;
Object $a = this.getA();
int result = result * 59 + ($a == null ? 43 : $a.hashCode());
Object $b = this.getB();
result = result * 59 + ($b == null ? 43 : $b.hashCode());
Object $obj2 = this.getObj2();
result = result * 59 + ($obj2 == null ? 43 : $obj2.hashCode());
return result;
}Obj2的hashCode方法
public int hashCode() {
int PRIME = true;
int result = 1;
Object $a = this.getA();
int result = result * 59 + ($a == null ? 43 : $a.hashCode());
Object $b = this.getB();
result = result * 59 + ($b == null ? 43 : $b.hashCode());
Object $obj1 = this.getObj1();
result = result * 59 + ($obj1 == null ? 43 : $obj1.hashCode());
return result;
}可以看到,計(jì)算obj1的hashcode,需要去獲取obj2的hashcode, 而計(jì)算obj2的hashcode ,又要去獲取obj1的hashcode。所以出現(xiàn)了死循環(huán)。
解決方案
不要使用@data, 使用@Getter, @Setter。
使用lombok還是要慎重啊。而且如果我們的SDK是對(duì)外提供的,那么務(wù)必不要使用。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決SpringBoot請(qǐng)求返回字符串中文亂碼的問題
這篇文章主要介紹了解決SpringBoot請(qǐng)求返回字符串中文亂碼的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
SpringBoot2開啟Actuator端點(diǎn)監(jiān)控的方法
這篇文章主要介紹了SpringBoot2開啟Actuator端點(diǎn)監(jiān)控的相關(guān)資料,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
Java并發(fā) CompletableFuture異步編程的實(shí)現(xiàn)
這篇文章主要介紹了Java并發(fā) CompletableFuture異步編程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Java 設(shè)計(jì)模式之責(zé)任鏈模式及異步責(zé)任鏈詳解
顧名思義,責(zé)任鏈模式(Chain of Responsibility Pattern)為請(qǐng)求創(chuàng)建了一個(gè)接收者對(duì)象的鏈。這種模式給予請(qǐng)求的類型,對(duì)請(qǐng)求的發(fā)送者和接收者進(jìn)行解耦。這種類型的設(shè)計(jì)模式屬于行為型模式2021-11-11
MyBatis-Plus中MetaObjectHandler沒生效完美解決
在進(jìn)行測(cè)試時(shí)發(fā)現(xiàn)配置的MyMetaObjectHandler并沒有生效,本文主要介紹了MyBatis-Plus中MetaObjectHandler沒生效完美解決,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11
Java設(shè)計(jì)模式之代理模式與@Async異步注解失效的解決
代理模式是Java常見的設(shè)計(jì)模式之一。所謂代理模式是指客戶端并不直接調(diào)用實(shí)際的對(duì)象,而是通過調(diào)用代理,來間接的調(diào)用實(shí)際的對(duì)象2022-07-07
使用shardingsphere對(duì)SQLServer坑的解決
本文主要介紹了使用shardingsphere對(duì)SQLServer坑的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03

