当前位置: 首页 > 科技观察

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

时间:2023-03-12 08:57:03 科技观察

本文转载自微信公众号《Java极客技术》,作者鸭血范唐。转载本文请联系Java极客技术公众号。一、Java简介,作为一门非常流行的编程语言,虽然它有非常丰富的语言特性,完全面向对象的编程,高度标准化的编程,但是它也有一个最受大家诟病的缺点:啰嗦,尤其是当你开发多年后,会明显感觉到,与动态语言相比,在java中定义变量之前,必须先创建一个类,然后再定义变量类型。每个类都需要写很多get/set/toString/hashCode/equals等方法。尤其是一个实体类有几十个变量的时候,写完get和set方法,一个实体类的长度差不多有上千行。为了避免写出这些“罗嗦”的方法,很多程序员一直在寻找一种工具可以让自己从这种重复性的工作中解脱出来,比如:idea,eclipse快速生成get和set方法的开发工具,还有就是这个今天要说的Lombok工具。2.LombokLombok是一款非常流行的代码简洁工具。利用它的注解特性,可以直接为我们省去上百行的get、set方法,操作非常方便。如果是idea开发工具,可以直接在preferences->plugins中搜索lombok,然后点击安装!然后,在项目工程中导入lombok依赖包!org.projectlomboklombok1.18.12provided最后只需要添加将@Data注解给对应的实体类,完成类属性的get/set注入。importlombok.Data;@DatapublicclassUser{privateStringid;privateStringage;privateStringname;//不需要显式写get和set方法}在类上使用@Data注解,本实体类中的属性不需要显式写get和set方法设置方法。对于这个类进行编译之后,我们打开User.class文件,看看编译后的文件内容长啥样?publicclassUser{privateStringid;privateStringage;privateStringname;publicUser(){}publicStringgetId()}{returningthis.getA{returnthis.age;}publicStringgetName(){returnthis.name;}publicvoidsetId(Stringid){this.id=id;}publicvoidsetAge(Stringage){this.age=age;}publicvoidsetName(Stringname){this.name=name;}publicbooleanequals(Objecto){if(o==this){returntrue;}elseif(!(oinstanceofUser)){returnfalse;}else{Userother=(User)o;if(!other.canEqual(this)){returnfalse;}else{label47:{Objectthis$id=this.getId();Objectother$id=other.getId();if(this$id==null){if(other$id==null){breaklabel47;}}elseif(this$id.equals(other$id)){breaklabel47;}returnfalse;}Objectthis$age=this.getAge();Objectother$age=other.getAge();if(this$age==null){if(other$age!=null){returnfalse;}}elseif(!this$age.equals(other$age)){returnfalse;}Objectthis$name=this.getName();Objectother$name=other.getName();if(this$name==null){if(other$name!=null){returnfalse;}}elseif(!this$name.equals(other$name)){returnfalse;}returntrue;}}}protectedbooleancanEqual(Objectother){returnoinstanceofUser;}publicinthashCode(){intPRIME=true;intresult=1;Object$id=this.getId();intresult=result*59+($id==null?43:$id.hashCode());Object$age=this.getAge();result=result*59+($age==null?43:$age.hashCode());Object$name=this.getName();result=result*59+($name==null?43:$name.hashCode());returnresult;}publicStringtoString(){return"User(id="+this.getId()+",age="+this.getAge()+",name="+this.getName()+")";}}很明显,User类在使用了@Data注解后,增加了get、set、hashCode、equals、toString方法。通过上面的例子可以发现,使用@Data注解可以大大减少代码量,使得代码非常简洁,这也是很多开发者热衷于使用Lombok的主要原因。Lombok的工作原理是如何实现的?由于Java正式版并没有为这种快速生成的方法提供注解工具,所以像Lombok这样的工具实际上使用了Java6的AnnotationProcessing技术和JSR269注入中实现的方法。简单的说,就是使用Java的非公开API。javac编译代码时,通过强类型转换得到JavacAnnotationProcessor对象,然后从JavacAnnotationProcessor的方法中得到抽象语法树(AST)进行强制修改,注入get、set等方法。使用Lombok最大的好处就是可以省去很多重复的代码,让代码更加简洁!但是也有很多缺点!3、缺点是什么?3.1.当你在使用Lombok时强制队友安装Lombok使用工具插件快速开发项目时,如果其他同事想与你协作开发项目,那么他必须安装Lombok插件,否则项目编译会报错。3.2.Decreasedcodedebuggability代码的可调试性将会降低。你为什么这么说?Lombok虽然省去了我们get和set方法的编程,但是如果我想知道是哪个方法设置了一个类的某个属性,如果使用native方法,就可以很好的知道调用者。但是如果你是用Lombok插件生成的,此时你是无从知晓的。连调试都没有办法!3.3.不懂Lombok注解,就踩坑了。我们知道使用@Data会重写hashCode()和equals()方法。如果是没有继承的单实体类,就不会用@Data来生成question。但是如果这个实体类继承了父类,那么@Data只会重写子类的hashCode()和equals()方法,不会添加父类的属性,这样就会造成,比如当你在使用HashMap使用当前实体类作为键时,可能会得到意想不到的结果。这种情况下,可以给类加上这个注解@EqualsAndHashCode(callSuper=true),子类的hashCode()和equals()方法会加上父类的属性。3.4.打破封装封装是java面向对象编程中一个非常重要的特性。例如,对于User实体类,我添加了一个新的标记属性。我只想暴露它的get方法,不想对外暴露set方法。不使用@Data注解时,我可以灵活编程,但是使用@Data注解后,属性标签就完全暴露在外界了。publicclassUser{privateStringid;privateStringage;privateStringname;privateStringtag="student";publicStringgetTag(){returntag;}}3.5、影响jdk升级其实上面的坑都不算大坑,在我看来最大的坑其实是working龙目岛的原则。它使用非官方支持的API接口,通过程序强制植入修改类,实现get、set等方法的注入。按照目前JDK的升级频率,每六个月就会发布一个新版本,但作为第三方工具,Lombok由开源团队维护,迭代速度无法保证。如果哪天JDK把这种后门给堵了,那Lombok基本就不能用了,到时候就是一件麻烦的事情。4.总结作为一款非常流行的工具插件,Lombok一定有自己的优势。日常开发中是否推荐使用,我个人持中立态度。如果你团队中的每个人都喜欢它,那么建议你使用它。在使用之前,最好训练一下有哪些陷阱,以免踩坑。如果大多数人不喜欢使用它,那么不建议您使用它。许多公司禁止您使用它。其实这种外挂有点类似于那种流氓外挂。工作原理并未以官方认可的方式实施。如果有一天新版本的jdk突然堵住了这个漏洞,那么项目升级jdk就比较困难了。因此,在评估是否在代码中引入Lombok时,可以在考虑它的优点的同时,考虑它会带来的问题,以便做出更好的决定!5.参考https://projectlombok.org/https://time.geekbang.org/column/article/164907http://blog.itpub.net/69908877/viewspace-2676272/