文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

为什么有的团队严禁使用Lombok?

2024-12-02 20:55

关注

一、介绍

Java,作为一款非常热门的编程语言,尽管它有着非常丰富的语言特性,完全面向对象编程,编程高度规范化,但是也有一个最受大家诟病的一个缺点:啰嗦,尤其是当你开发了很多年之后,你会明显的感受到,相比动态语言,java 定义变量之前,要先创建类,然后定义变量类型,每个类要写很多的get/set/toString/hashCode/equals等等方法。

尤其是当一个实体类,高达几十个变量时,写完get、set方法之后,一个实体类的长度快接近一千行。

为了避免写这些“罗嗦”的方法,很多程序员一直在寻觅着找一个能够使他们摆脱这种重复劳动工作的工具,例如:idea、eclipse 开发工具的快捷生成get、set方法的工具,还有我们今天要谈论的这个Lombok工具。

二、Lombok

Lombok 是一款非常流行的代码简洁工具,利用它的注解特性,直接就可以帮我们省去高大几百行的get、set方法,操作非常方便。

如果是idea开发工具,可以直接在preferences -> plugins里面搜索lombok,然后点击安装即可!

接着,在项目工程中导入lombok依赖包!

  1.  
  2.     org.projectlombok 
  3.     lombok 
  4.     1.18.12 
  5.     provided 
  6.  

 

最后,只需要在对应的实体类上加上@Data注解,即可完成类属性get/set的注入。

  1. import lombok.Data; 
  2.  
  3. @Data 
  4. public class User { 
  5.     private String id; 
  6.     private String age; 
  7.     private String name
  8.   
  9.  //可以不用显式写get、set方法 

使用@Data注解在类上,这个实体类中的属性就不需要显式写get、set方法了。

对这个类进行编译之后,我们打开User.class文件,看看编译后的文件内容长啥样?

  1. public class User { 
  2.     private String id; 
  3.     private String age; 
  4.     private String name
  5.  
  6.     public User() { 
  7.     } 
  8.  
  9.     public String getId() { 
  10.         return this.id; 
  11.     } 
  12.  
  13.     public String getAge() { 
  14.         return this.age; 
  15.     } 
  16.  
  17.     public String getName() { 
  18.         return this.name
  19.     } 
  20.  
  21.     public void setId(String id) { 
  22.         this.id = id; 
  23.     } 
  24.  
  25.     public void setAge(String age) { 
  26.         this.age = age; 
  27.     } 
  28.  
  29.     public void setName(String name) { 
  30.         this.name = name
  31.     } 
  32.  
  33.     public boolean equals(Object o) { 
  34.         if (o == this) { 
  35.             return true
  36.         } else if (!(o instanceof User)) { 
  37.             return false
  38.         } else { 
  39.             User other = (User)o; 
  40.             if (!other.canEqual(this)) { 
  41.                 return false
  42.             } else { 
  43.                 label47: { 
  44.                     Object this$id = this.getId(); 
  45.                     Object other$id = other.getId(); 
  46.                     if (this$id == null) { 
  47.                         if (other$id == null) { 
  48.                             break label47; 
  49.                         } 
  50.                     } else if (this$id.equals(other$id)) { 
  51.                         break label47; 
  52.                     } 
  53.  
  54.                     return false
  55.                 } 
  56.  
  57.                 Object this$age = this.getAge(); 
  58.                 Object other$age = other.getAge(); 
  59.                 if (this$age == null) { 
  60.                     if (other$age != null) { 
  61.                         return false
  62.                     } 
  63.                 } else if (!this$age.equals(other$age)) { 
  64.                     return false
  65.                 } 
  66.  
  67.                 Object this$name = this.getName(); 
  68.                 Object other$name = other.getName(); 
  69.                 if (this$name == null) { 
  70.                     if (other$name != null) { 
  71.                         return false
  72.                     } 
  73.                 } else if (!this$name.equals(other$name)) { 
  74.                     return false
  75.                 } 
  76.  
  77.                 return true
  78.             } 
  79.         } 
  80.     } 
  81.  
  82.     protected boolean canEqual(Object other) { 
  83.         return other instanceof User
  84.     } 
  85.  
  86.     public int hashCode() { 
  87.         int PRIME = true
  88.         int result = 1; 
  89.         Object $id = this.getId(); 
  90.         int result = result * 59 + ($id == null ? 43 : $id.hashCode()); 
  91.         Object $age = this.getAge(); 
  92.         result = result * 59 + ($age == null ? 43 : $age.hashCode()); 
  93.         Object $name = this.getName(); 
  94.         result = result * 59 + ($name == null ? 43 : $name.hashCode()); 
  95.         return result; 
  96.     } 
  97.  
  98.     public String toString() { 
  99.         return "User(id=" + this.getId() + ", age=" + this.getAge() + ", name=" + this.getName() + ")"
  100.     } 

很清晰的看到,使用@Data注解之后,User类新增了get、set、hashCode、equals和toString方法。

通过上面的例子,大家可以发现,使用@Data注解可以大大减少了代码量,使代码非常简洁,这也是很多开发者热衷于使用Lombok的主要原因。

Lombok的工作原理是怎么实现的呢?

由于Java的官方版本没有提供这种快速生成方法的注解工具,类似Lombok这样的工具,其实都是使用了从Java 6和JSR 269的Annotation Processing技术中实现方法的注入。

简单的说,就是使用了 Java 非公开的 API,在 javac 编译代码时,通过强类型转换获取JavacAnnotationProcessor对象,再从JavacAnnotationProcessor的方法里面拿到抽象语法树(AST)做强制修改,注入get、set等方法。

使用Lombok这种方案,有个最大的好处,就是可以节省大量的重复代码,让代码更佳简洁!但是也有很多弊端!

三、有哪些坏处呢?

3.1、强迫队友也安装 Lombok

当你在使用Lombok工具插件来快速开发项目的时候,如果别的同事也要和你一起协作开发项目,那么他不得不也要安装Lombok插件,不然项目编译会报错。

3.2、代码可调试性降低

代码可调试性会降低,为什么会这么说呢?

Lombok虽然给我们节省了get和set方法的编程,但是如果我想知道类的某个属性被哪些方法操作给set了,如果用原生的方法,可以很好的知道调用方。但是如果使用Lombok插件来生成,这个时候你根本无从得知。甚至没办法调试!

3.3、不懂 Lombok 注解,会踩坑

我们知道,使用@Data会重写hashCode()和equals()方法,如果是单个实体类,没有继承的话,你使用@Data不会产生问题。

但是如果这个实体类又继承了父类,@Data只会重写子类的hashCode()和equals()方法,不会把父类的属性加进去,这样就会导致,例如当你在使用HashMap的时候,用当前这个实体类作为key,可能会得到意想不到的结果。

遇到这种情况,你可以在类上加上这个注解@EqualsAndHashCode(callSuper=true),子类的hashCode()和equals()方法会加入父类的属性。

4、破坏封装性

封装是 java 面向对象编程中非常重要的一个特性。

例如,针对User实体类,我新加一个tag属性,我只想暴露它的get方法,不想暴露set方法给外部,没有用@Data注解的时候,我可以很灵活的进行编程,但是使用@Data注解之后,属性tag被完全暴露在外界了。

  1. public class User { 
  2.  
  3.     private String id; 
  4.  
  5.     private String age; 
  6.  
  7.     private String name
  8.  
  9.     private String tag = "学生"
  10.  
  11.     public String getTag() { 
  12.         return tag; 
  13.     } 
  14.      

3.5、影响 jdk 升级

其实以上的坑点,都不算什么很大的坑点,在我看来,最大的坑点其实就是Lombok的工作原理,使用了非官方支持的 API 接口,通过程序强制植入方式来修改类,实现get、set等方法的注入。

按照如今 JDK 的升级频率,每半年都会推出一个新的版本,但是Lombok作为一个第三方工具,并且是由开源团队维护的,那么他的迭代速度是无法保证的。

假如某天JDK把这种后门堵住了,那Lombok基本上就不能用了,到时候又是个麻烦事情。

四、总结

Lombok 作为一款非常流行的工具插件,肯定有它自身的优势所在,到底建不建议在日常开发中使用,我个人其实是一个中立的态度,如果你们团队的人都喜欢它,那推荐你使用,在使用之前,最好培训一下,有哪些坑点,避免踩坑。

如果多数人不太喜欢用它,那就不推荐你使用,很多公司禁止你使用它的原因,其实这种插件有点类似那种流氓插件,工作原理不是官方所认可的方式来实现,假如某天新版本的 jdk 突然把这个漏洞给堵住了,那么项目想要升级 jdk,就比较困难。

因此大家在评估要不要在代码中引入Lombok的时候,在想它的优点同时,能够考虑到它会带来的哪些问题,以便更好的做决定!

五、参考

https://projectlombok.org/

https://time.geekbang.org/column/article/164907

http://blog.itpub.net/69908877/viewspace-2676272/

 

来源:Java极客技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯