频道栏目
首页 > 程序开发 > 软件开发 > 其他 > 正文
Lombok 工具中@Data注解的使用说明
2018-05-19 14:12:14         来源:Brucelwl的博客  
收藏   我要投稿
看了大学一位同学博客,写了内容大致就是对于一个类中出现了该类的集合,通过Lombok的@Data注解生成class文件,当创建两个这个类的对象并且互相之间引用的时候,就出现了StackOverflowError异常,即栈溢出,或者叫超出栈深度. 在Java虚拟机内存区域分为两种一种是线程共享区域,另一种是线程私有区域,而虚拟机栈就处在线程私有区域中,虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,栈帧用于存储局部变量表,操作数栈,动态链接,方法返回地址等等。

\

Java 虚拟机规范中,对这个区域规定了两种异常情况:
  • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。
  • 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

    下面给出个内存区域内存溢出的简单测试方法,

    \

    回到文章讨论的问题,@Data注解在什么情况下可能导致StackOverflowError情况呢?先看下同学给出的示例代码,

    @Data
    public class Project {
        private Long id;
        private String projectName;
        private List projects;
    
        public static void main(String[] args) {
            Project project1 = new Project();
            Project project2 = new Project();
            project1.setProjects(Arrays.asList(project2));
            project2.setProjects(Arrays.asList(project1));
            System.out.println(project1.hashCode());
        }
    }
    从代码可以看出project1引用了project2,project2引用了project1,同学给出的解释如下:“ @Data 注解不仅帮我们实现了生成了getter/setter同时还重写了equals(Object other) 和 hashCode()方法, Lombok 会将 Project 类中的 List projects 当做是 hashCode 计算的一部分(同理,equals,toString 也会存在同样的问题),而如果我的项目中出现循环引用,这就会导致死循环,最终就会抛出 StackOverFlowError。”,

    这时候我就有一个疑问了,难道相互引用就一定出现死循环吗?好吧,我也来看看反编译下@Data到底干啥了,代码反编译后确实发现hashCode()方法被Lombok自己生成了,代码如下,

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null  43 : $id.hashCode());
        Object $projectName = this.getProjectName();
        result = result * 59 + ($projectName == null  43 : $projectName.hashCode());
        Object $projects = this.getProjects();
        result = result * 59 + ($projects == null  43 : $projects.hashCode());
        return result;
    }

    那怎么就死循环了呢,其实问题在于projects是一个ArrayList集合,ArrayList对hashCode() 的计算会把每一个元素拿出来调用元素的hashCode()求和,但是projects里面的元素是 project,project里面又有projects,因此出现无限递归调用,又是单线程中调用方法,所以就抛出StackOverflowError,在大多数场景中我们使用Lombok的@Data注解目的是为了生成getter/setter,不需要生成hashCode()和equals()方法,即使业务需要判断两个对象是否相等,逻辑基本也不会是lombok生成的那种,所以建议使用 @Getter 和 @Setter 替换 @Data注解

    ArrayList的hashCode()代码如下:

    public static int hashCode(Object a[]) {
        if (a == null)
            return 0;
        int result = 1;
        for (Object element : a)
            result = 31 * result + (element == null  0 : element.hashCode());
        return result;
    }
点击复制链接 与好友分享!回本站首页
相关TAG标签 注解 Lombok 工具
上一篇:LM最优化算法
下一篇:选择排序算法
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站