• & @Data导致栈溢出StackOverflowError


    使用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);
        }
    }

    执行结果:栈溢出

    image-20210725134245051

    问题分析

    查看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());

    同样会出现栈溢出

    image-20210725140207387

    原因是 计算user的hashcode,需要去获取role的hashcode, 而计算role的hashcode ,又要去获取user的hashcode。所以出现了死循环。

    解决方案

    不要使用@Data, 换为使用@Getter, @Setter。

    总结

    User->Role , Role->User 循环引用

    当两个类,有循环引用时,使用lombok注解@Data,会重写hashCode()和toString()方法,造成死循环!!!

  • 相关阅读:
    Django的sitemap
    meibu ddns update command
    nginx笔记
    docker里运行cron的要点笔记
    win2008r2 32位odbc安装笔记
    【转载】利用tasker推送手机短信到企业微信(App或者微信公众号)
    关闭树莓派的优化笔记
    自已编译openweb docker image笔记
    【笔记】元学习专题视频(台大·李宏毅)学习记录
    【教程】基于Ubuntu系统的PyTorch虚拟环境配置
  • 原文地址:https://www.cnblogs.com/doagain/p/15057816.html
Copyright © 2020-2023  润新知