使用lombok的@Data会导致栈溢出StackOverflowError。
问题代码
用户->角色->权限
@Data
class SysUser{
private Set<SysRole> roles;
}
@Data
class SysRole{
private Set<SysUser> users;
}
import lombok.Data;
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
SysUser user = new SysUser();
SysRole role = new SysRole();
Set<SysUser> users = new HashSet<>();
users.add(user);
Set<SysRole> roles = new HashSet<>();
roles.add(role);
user.setRoles(roles);
role.setUsers(users);
System.out.println(user);
// System.out.println(role);
}
}
执行结果:栈溢出
问题分析
查看class文件
import java.util.Set;
class SysUser {
private Set<SysRole> roles;
public SysUser() {
}
public Set<SysRole> getRoles() {
return this.roles;
}
public void setRoles(final Set<SysRole> roles) {
this.roles = roles;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof SysUser)) {
return false;
} else {
SysUser other = (SysUser)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$roles = this.getRoles();
Object other$roles = other.getRoles();
if (this$roles == null) {
if (other$roles != null) {
return false;
}
} else if (!this$roles.equals(other$roles)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof SysUser;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $roles = this.getRoles();
int result = result * 59 + ($roles == null ? 43 : $roles.hashCode());
return result;
}
public String toString() {
return "SysUser(roles=" + this.getRoles() + ")";
}
}
import java.util.Set;
class SysRole {
private Set<SysUser> users;
public SysRole() {
}
public Set<SysUser> getUsers() {
return this.users;
}
public void setUsers(final Set<SysUser> users) {
this.users = users;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof SysRole)) {
return false;
} else {
SysRole other = (SysRole)o;
if (!other.canEqual(this)) {
return false;
} else {
Object this$users = this.getUsers();
Object other$users = other.getUsers();
if (this$users == null) {
if (other$users != null) {
return false;
}
} else if (!this$users.equals(other$users)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof SysRole;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $users = this.getUsers();
int result = result * 59 + ($users == null ? 43 : $users.hashCode());
return result;
}
public String toString() {
return "SysRole(users=" + this.getUsers() + ")";
}
}
@Data重写了ToString方法,出现了循环打印。
进一步测试
打印user的hashcode方法
System.out.println(user.hashCode());
同样会出现栈溢出
原因是 计算user的hashcode,需要去获取role的hashcode, 而计算role的hashcode ,又要去获取user的hashcode。所以出现了死循环。
解决方案
不要使用@Data, 换为使用@Getter, @Setter。
总结
User->Role , Role->User 循环引用
当两个类,有循环引用时,使用lombok注解@Data,会重写hashCode()和toString()方法,造成死循环!!!