如果您正在阅读本文,您可能已经了解ProjectLombok一段时间了。你准备好拥抱龙目岛了吗?或者你准备好向你的团队推荐这么酷的项目了吗?如果您准备好这样做,这是我对Lombok一年的看法。我承认Lombok是一个非常优秀的Java库。它可以让您在编写更少代码的同时玩得更酷。几个简单的注解可以杀死一大段模板代码。但是,所有的源代码都是用来阅读很多时间的,只有很少的时间用来执行(这句话大家可以仔细看)。一年前,我和大多数人都认为Lombok的出现会让Java编码体验更好,并强烈推荐我的团队使用Lombok。一年后,我开始有这方面的顾虑,尤其是当我准备为开源博客系统Una-Boot升级Java版本时,才发现Lombok自己掉进了陷阱。在我进一步分析它的源代码并了解相关注解的工作原理后,我发现我不需要使用非标准的第三方库来将Java转换成一门简洁酷炫的语言。Lombok的引入让我的项目获得了暂时的成功,但是暂时成功的代价是随着项目的推进,技术债开始积累。接下来,我会用几个熟悉的场景来重温一下我是如何落入Lombok的诡计陷阱的。爱的开始,恨的起源面对Lombok提供的众多“神位”,你不介意给IDE加个新插件。IntelliJIDEA玩家只需搜索“LombokPlugin”即可找到此神器并安装。爱上Lombok是从安装Lombok插件开始的,仇恨也从此萌芽。在使用Lombok之前,我们的源代码看起来是这样的:Stringname){this.name=name;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicintgetGender(){returngender;}publicvoidsetGender(intgender){this.gender=gender;}@Overridepublicbooleanequals(Objecto){if(this==o){returntrue;}if(o==null||getClass()!=o.getClass()){returnfalse;}MyObjectobj=(MyObject)o;returnage=obj.age&&gender=obj.gender&&Objects.equals(id,obj.id)&&Objects.queals(name,obj.name);}@OverridepublicinthashCode(){returnObjects.hash(id,name,age,gender);}@OverridepublicStringtoString(){return"MyObject{"+"id="+id+"name="+name+"age="+age+"gender="+gander+"}";}}每个JavaBean都会像上面说的那样填充getters和setters,equals,hashCode和toString模板代码,这看起来像个胖子(不得不承认Java是一门有缺陷的编程语言)当我们安装Lombok插件时,IDE可以识别它很酷的注解,使用Lombok的@Getter和@Setter注解最后,代码会看起来像这样苗条:@Getter@SetterpublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;@Overridepublicbooleanequals(Objecto){if(this==o){returntrue;}if(o==null||getClass()!=o.getClass()){returnfalse;}MyObjectobj=(MyObject)o;returnage=obj.age&&gender=obj.gender&&Objects.equals(id,obj.id)&&Objects.queals(name,obj.name);}@OverridepublicinthashCode(){returnObjects.hash(id,name,age,gender);}@OverridepublicStringtoString(){return"MyObject{"+"id="+id+"name="+name+"age="+age+"gender="+gander+"}";}}你认为Lombok有这个能力吗?它还使代码的“主体”更苗条、更邪恶。上面的代码还有改进的余地。我们可以用@EqualsAndHashCod注解替换equals和hashCode方法:@Getter@Setter@EqualsAndHashCodepublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;@OverridepublicStringtoString(){return"MyObject{"+"id="+id+"name="+name+"age="+age+"gender="+gander+"}";}}现在的代码看起来好多了吗?但这不是最好的时机。现在其他方法已被替换,让我们也删除toString方法。如你所愿,你可以使用@ToString注解去掉对应的方法:@Getter@Setter@EqualsAndHashCode@ToStringpublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;}在Lomboktrick之后,和原来的代码相比,是不是又酷又瘦又性感呢?你以为就这样结束了吗?远不止于此。你会发现类名上的很多注解看起来很别扭。Lombok提供了一个组合注解@Data,可以代替类名头部的象样的东西:@DatapublicclassMyObject{privateLongid;privateStringname;privateintage;privateintgender;现在,Lombok是否使您的对象成为您心目中的完美外观?恶魔之“体”,清冷脱俗。Lombok还有一些其他的注解,比如@Slf4j、@NoArgsConstructor、@AllArgsConstructor等,Lombok的用法介绍不是本文的重点。上面代码行数的变化过程,可能是无数程序员爱上Lombok的主要原因。就像一个肥胖的人逐渐变成一个苗条的人。同时也让你看到一个现象:你觉得程序员懒惰吗?其他时候他们比你想象的更懒惰。虽然很酷,但它也为代码种下了诅咒。扭曲的审美,爱情隐患扭曲的审美导致被检查对象处于亚健康状态。使用Lombok插件后,我们的代码也处于“亚健康”状态。回到最开始的那句话:所有的源代码,大量的时间是用来阅读的,只有少量的时间是用来执行的。本质上,我们都在寻求减少程序中的样板代码,使其代码更加简洁明了,从而提高代码的可读性和可维护性。但是龙目岛并没有实现我们追求的愿景。它只是利用了Java语言在编译期的空隙期,用了一种刁钻的方式,将我们需要的方法注入(写)到当前类中。在中,这个过程很像破解我们的代码,只是一个看起来很酷的技巧。这种trick既不聪明也不安全,反而会破坏Java代码已有的特性和代码的可读性。下面结合自己使用Lombok后的感受,谈谈Lombok带来的几大痛点。1.JDK版本问题当我想将现有项目的JDK从Java8升级到Java11时,发现Lombok无法正常运行。所以只好把项目源码中所有的Lombok注解清除掉,使用IDE自带的函数生成getter/setter、equals、hashCode、toString、constructor方法。您还可以使用Delombok工具来完成此过程。但这毕竟会消耗你大量的时间。2.强制使用当你在源代码中使用了Lombok,而你的代码刚好被其他人使用,那么依赖你代码的人也必须安装Lombok插件(不管他们喜不喜欢),并且在同时花时间了解Lombok注解的使用,如果不这样做,代码将无法正常运行。在使用了Lombok之后,我发现这是一个非常流氓的行为。3、可读性差Lombok隐藏了JavaBean封装的细节。如果使用@AllArgsConstructor注解,它会提供一个巨大的构造函数,让外界有机会在对象初始化时修改类中的所有属性。首先,这是极不安全的,因为我们不想修改类中的某些属性;另外,如果一个类中有几十个属性,就会有一个包含几十个参数的构造函数被删除。Lombok注入类,属于非理性行为;其次,构造函数参数的顺序完全由Lombok控制,我们无法控制,只有当你需要调试的时候,你才会发现有一个奇怪的“小强”在等着你;最后,在运行代码之前,你可以只能想象它们在所有JavaBean方法中是什么样子,你是看不到它们的。4.增加代码耦合当你使用Lombok编写某个模块的代码时,其他依赖该模块的代码需要导入Lombok依赖,同时你还需要在IDE中安装Lombok插件。Lombok的依赖包虽然不大,但是因为在一个地方使用Lombok,其他所有依赖方都必须强制加入Lombok的Jar包。这是一种侵入式耦合。如果再出现JDK版本问题,那就惨了。5.得不偿失使用Lombok,一时觉得很爽,但是污染了你的代码,破坏了Java代码的完整性、可读性和安全性,同时增加了团队的技术债。得不偿失。如果你真的想让你的代码更简洁,同时兼顾可读性和编码效率,你还不如使用主流的Scala或Kotlin这种基于JVM的语言。总结Lombok本身就是一个优秀的Java代码库。它使用巧妙的语法糖来简化Java编码,并提供一种简化Java代码的方法。但是,在使用这个代码库的时候,需要了解Lombok并不是一个标准的Java库。使用Lombok会增加团队的技术债,降低代码的可读性,增加代码的耦合和调试难度。Lombok虽然在一定程度上减少了样板代码的编写,但也带来了一些未知的风险。如果你参与的是团队项目(或大型项目),请与你的团队沟通,考虑到后续的升级和扩展,再三考虑是否使用Lombok。
