使用lombok的@Data會導(dǎo)致棧溢出StackOverflowError問題
最近擼代碼發(fā)現(xiàn)一個問題,使用lombok的@Data會導(dǎo)致棧溢出StackOverflowError。
問題復(fù)現(xiàn)
兩個類,有循環(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)上述問題的場景是出現(xiàn)了循環(huán)依賴。
@Data注解在什么情況下可能導(dǎo)致StackOverflowError情況呢?原因在于@Data重寫了hashCode()方法。
我們看一下兩個類的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;
}可以看到,計算obj1的hashcode,需要去獲取obj2的hashcode, 而計算obj2的hashcode ,又要去獲取obj1的hashcode。所以出現(xiàn)了死循環(huán)。
解決方案
不要使用@data, 使用@Getter, @Setter。
使用lombok還是要慎重啊。而且如果我們的SDK是對外提供的,那么務(wù)必不要使用。以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot2開啟Actuator端點(diǎn)監(jiān)控的方法
這篇文章主要介紹了SpringBoot2開啟Actuator端點(diǎn)監(jiān)控的相關(guān)資料,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
Java并發(fā) CompletableFuture異步編程的實(shí)現(xiàn)
這篇文章主要介紹了Java并發(fā) CompletableFuture異步編程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Java 設(shè)計模式之責(zé)任鏈模式及異步責(zé)任鏈詳解
顧名思義,責(zé)任鏈模式(Chain of Responsibility Pattern)為請求創(chuàng)建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發(fā)送者和接收者進(jìn)行解耦。這種類型的設(shè)計模式屬于行為型模式2021-11-11
MyBatis-Plus中MetaObjectHandler沒生效完美解決
在進(jìn)行測試時發(fā)現(xiàn)配置的MyMetaObjectHandler并沒有生效,本文主要介紹了MyBatis-Plus中MetaObjectHandler沒生效完美解決,具有一定的參考價值,感興趣的可以了解一下2023-11-11
Java設(shè)計模式之代理模式與@Async異步注解失效的解決
代理模式是Java常見的設(shè)計模式之一。所謂代理模式是指客戶端并不直接調(diào)用實(shí)際的對象,而是通過調(diào)用代理,來間接的調(diào)用實(shí)際的對象2022-07-07
使用shardingsphere對SQLServer坑的解決
本文主要介紹了使用shardingsphere對SQLServer坑的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03

