如果你不知道,Project Lombok帮助解决了Java的一些麻烦,比如用注释生成getter和setter,甚至是简单的JavaBean,比如用@Data生成。它真的可以帮助我,特别是在50个不同的事件对象中,你有多达7个不同的字段需要用getter来构造和隐藏。我可以用这个删除几乎一千行代码。

然而,我担心从长远来看,这将是一个后悔的决定。当我提到它的时候,火焰战争就会在##Java Freenode频道爆发,提供代码片段会让可能的助手感到困惑,人们会抱怨缺少JavaDoc,而未来的提交者可能无论如何都会删除它。我很享受积极的一面,但我担心消极的一面。

那么:在任何项目中使用Lombok安全吗?积极的影响抵得上消极的影响吗?


听起来好像您已经认为Project Lombok为您提议的新项目提供了显著的技术优势。(首先要澄清的是,我对龙目岛项目没有特别的看法,无论如何。)

在某些项目(开源或其他方式)中使用Project Lombok(或任何其他改变游戏规则的技术)之前,您需要确保项目涉众同意这一点。这包括开发人员和任何重要的用户(例如,正式或非正式的赞助商)。

你提到了这些潜在的问题:

当我提到它时,火焰战争将在##Java Freenode频道爆发,

一件容易的事。忽略/不要参与战火,或者只是避免提及龙目岛。

提供代码片段会让可能的助手感到困惑,

如果项目策略是使用Lombok,那么可能的助手将需要习惯它。

人们会抱怨缺少JavaDoc,

这是他们的问题。心智正常的人都不会把自己组织的源代码/文档规则死板地应用到第三方开源软件上。项目团队应该可以自由地设置与所使用的技术相适应的项目源代码/文档标准。

(跟进- Lombok开发人员认识到,不为合成的getter和setter方法生成javadoc注释是一个问题。如果这是您的项目的主要问题,那么另一种选择是创建并提交Lombok补丁来解决这个问题。)

未来的提交者可能会把它全部删除。

那没开!如果商定的项目策略是使用Lombok,那么毫无理由地去Lombok代码的提交者应该受到惩罚,如果有必要,他们的提交权将被撤销。

当然,这是假设你已经得到了涉众的支持……包括开发者。它还假定你已经准备好为自己的理由辩护,并适当地处理不可避免的不同声音。


继续使用Lombok吧,如果有必要,您可以在之后“delombok”您的代码http://projectlombok.org/features/delombok.html


我个人(因此也是主观上)发现,与IDE/自己实现的复杂方法(如hashcode & equals)相比,使用Lombok使我的代码更能表达我想要实现的目标。

当使用

@EqualsAndHashCode(callSuper = false, of = { "field1", "field2", "field3" })

与任何IDE/自己的实现相比,保持Equals & HashCode一致并跟踪哪些字段被求值要容易得多。当您仍然定期添加/删除字段时,这一点尤其正确。

@ToString注释及其参数也是如此,它们清楚地传达了所期望的行为,包括包含/排除字段、getter的使用或字段访问,以及是否调用super.toString()。

同样,通过使用@Getter或@Setter(AccessLevel.NONE)注释整个类(并可选择覆盖任何发散的方法),可以立即清楚哪些方法将可用于字段。

好处无穷无尽。

在我看来,这不是关于减少代码,而是关于清楚地传达您想要实现的目标,而不是必须从Javadoc或实现中找到答案。减少的代码只是使它更容易发现任何发散方法实现。


当我向我的团队展示项目时,他们的热情很高,所以我认为你不应该害怕团队的反应。

就ROI而言,集成它很简单,并且不需要对其基本形式进行代码更改。(只需向类中添加一个注释) 最后,如果您改变了主意,您可以运行unlombok,或让IDE创建这些setter、getter和ctor(我认为一旦他们看到您的pojo变得多么清晰,就没有人会要求它们了)


在过去的一年里,我在几乎所有的项目中都使用了Lombok,但不幸的是,我把它移除了。在一开始,这是一种非常干净的开发方式,但为新团队成员设置开发环境并不是非常容易和直接的。头痛时,我就把它去掉了。但这是一个很好的工作,需要一些更简单的设置。


TL;博士:

是的,使用起来很安全,我建议使用它。(2022年5月)


原来的答案

今天刚开始使用龙目岛。到目前为止,我很喜欢它,但我没有看到它的一个缺点是重构支持。

如果您有一个带有@Data注解的类,它将根据字段名为您生成getter和setter。如果您在另一个类中使用这些getter中的一个,然后确定该字段的命名很糟糕,它将不会找到这些getter和setter的用法,并将旧名称替换为新名称。

我认为这必须通过IDE插件来完成,而不是通过Lombok。

更新(2013年1月22日) 在使用Lombok 3个月之后,我仍然推荐它用于大多数项目。然而,我确实发现了另一个与上面列出的类似的缺点。

如果你有一个类,比如MyCompoundObject.java,它有2个成员,都用@Delegate标注,比如myWidgets和myGadgets,当你从另一个类调用myCompoundObject.getThingies()时,不可能知道它是委托给小部件还是小工具,因为你不能再跳到IDE中的源代码。

使用Eclipse“Generate Delegate Methods…”为您提供了相同的功能,同样快速,并提供了源跳转。缺点是它用样板代码把你的源代码弄得一团糟,使你的注意力从重要的东西上转移开。

更新2(2013年2月26日) 5个月后,我们仍在使用Lombok,但我还有其他一些烦恼。当您试图熟悉新代码时,缺少声明的getter和setter可能会令人恼火。

例如,如果我看到一个名为getDynamicCols()的方法,但我不知道它是关于什么的,我就需要跨越一些额外的障碍来确定这个方法的目的。其中一些障碍是Lombok,一些是缺乏Lombok智能插件。障碍包括:

Lack of JavaDocs. If I javadoc the field, I would hope the getter and setter would inherit that javadoc through the Lombok compilation step. Jump to method definition jumps me to the class, but not the property that generated the getter. This is a plugin issue. Obviously you are not able to set a breakpoint in a getter/setter unless you generate or code the method. NOTE: This Reference Search is not an issue as I first thought it was. You do need to be using a perspective that enables the Outline view though. Not a problem for most developers. My problem was I am using Mylyn which was filtering my Outline view, so I didn't see the methods. Lack of References search. If I want to see who's calling getDynamicCols(args...), I have to generate or code the setter to be able to search for references.

UPDATE 3 (Mar 7 '13) Learning to use the various ways of doing things in Eclipse I guess. You can actually set a conditional breakpoint (BP) on a Lombok generated method. Using the Outline view, you can right-click the method to Toggle Method Breakpoint. Then when you hit the BP, you can use the debugging Variables view to see what the generated method named the parameters (usually the same as the field name) and finally, use the Breakpoints view to right-click the BP and select Breakpoint Properties... to add a condition. Nice.

更新4(2013年8月16日) Netbeans不喜欢在Maven pom中更新Lombok依赖项。项目仍然会编译,但是文件会因为有编译错误而被标记,因为它看不到Lombok正在创建的方法。清除Netbeans缓存可以解决这个问题。不确定是否有像Eclipse中那样的“清洁项目”选项。小问题,但我想让大家知道。

更新5(2014年1月17日) Lombok与Groovy(至少Groovy -eclipse-编译器)的配合并不总是很好。您可能不得不降低编译器的版本。 Maven Groovy和Java + Lombok

更新6(2014年6月26日) 警告一句。Lombok有点让人上瘾,如果您从事的项目由于某种原因不能使用它,它会让您感到厌烦。你最好永远不要使用它。

更新7(2014年7月23日) 这是一个有趣的更新,因为它直接解决了OP所询问的采用Lombok的安全性问题。

从v1.14开始,@Delegate注释已经降级为实验性状态。详细信息记录在他们的网站上(Lombok Delegate Docs)。

问题是,如果你使用这个功能,你的退出选项是有限的。我认为选项如下:

手动删除@Delegate注释并生成/手工编码委托代码。如果在注释中使用属性,这就有点困难了。 Delombok那些有@Delegate注释的文件,你也可以添加回你想要的注释。 永远不要更新Lombok或维护一个分叉(或使用体验特性)。 Delombok您的整个项目,停止使用Lombok。

据我所知,Delombok没有删除注释子集的选项;至少对于单个文件的上下文中是这样的。我打开了一个请求使用Delombok旗帜的功能的票据,但我不希望在不久的将来实现。

更新8(2014年10月20日) 如果您可以选择使用Groovy, Groovy提供了与Lombok相同的大部分优点,还提供了大量其他特性,包括@Delegate。如果您认为很难将这个想法推销给当权者,请查看@CompileStatic或@TypeChecked注释,看看它们是否对您的事业有帮助。事实上,Groovy 2.0发行版的主要关注点是静态安全。

更新9(2015年9月1日) Lombok仍在积极维护和增强,这预示着采用的安全水平良好。@Builder注释是我最喜欢的新特性之一。

更新10(11月17日至15日) 这似乎与OP的问题没有直接关系,但值得分享。如果您正在寻找工具来帮助您减少所编写的样板代码的数量,您还可以查看谷歌Auto -特别是AutoValue。如果你看一下他们的幻灯片,就会发现龙目岛是他们试图解决问题的可能解决方案。他们列出的龙目岛的缺点是:

插入的代码是不可见的(你不能“看到”它生成的方法)[注:实际上你可以,但它只需要一个反编译器] 编译器hack是不标准的和脆弱的 “在我们看来,你的代码不再是真正的Java”

我不确定我在多大程度上同意他们的评价。考虑到幻灯片中记录的AutoValue的缺点,我将坚持使用Lombok(如果Groovy不是一个选项)。

更新11(2016年2月8日) 我发现Spring Roo有一些类似的注释。我有点惊讶地发现Roo仍然存在,并且查找注释的文档有点粗糙。移除看起来也不像去龙目岛那么容易。龙目岛似乎是更安全的选择。

更新12(2016年2月17日) 当我试图为我目前正在从事的项目提出为什么使用Lombok是安全的理由时,我发现了v1.14中添加的一块黄金-配置系统!这意味着您可以配置项目以禁止团队认为不安全或不可取的某些特性。更好的是,它还可以使用不同的设置创建特定于目录的配置。这太棒了。

更新13(16年10月4日) 如果这类事情对您很重要,Oliver Gierke认为将Lombok添加到Spring Data Rest是安全的。

更新14(17年9月26日) 正如@gavenkoa在OPs问题的评论中指出的那样,JDK9编译器支持还不可用(Issue #985)。这听起来对龙目岛团队来说也不是一个容易解决的问题。

更新15(18年3月26日) Lombok更新日志显示,v1.16.20“现在可以在JDK1.9上编译Lombok”,尽管#985仍然是开放的。

然而,为了适应JDK9而进行的更改需要一些突破性的更改;所有这些都与配置默认值中的更改隔离。有点令人担忧的是,他们引入了突破性的更改,但该版本只是增加了“增量”版本号(从v1.16.18到v1.16.20)。由于这篇文章是关于安全的,如果你有一个像yarn/npm这样的构建系统,它会自动升级到最新的增量版本,你可能会猛然醒悟。

更新16(19年1月9日)

似乎JDK9的问题已经解决,Lombok可以使用JDK10,据我所知,甚至JDK11。

我注意到一件从安全角度考虑的事情是,从v1.18.2到v1.18.4的变更日志列出了两个“突破性变更”!?我不确定一个突破性的变化是如何发生在一个永久的“补丁”更新。如果您使用自动更新补丁版本的工具,可能会出现问题。

更新17(3月17日21日)

围绕JDK 16, Lombok开发人员和OpenJDK开发人员之间发生了一些戏剧性的变化。JDK开发人员认为,Lombok通过JDK团队想要关闭的漏洞利用了未发布的JDK内部,但由于各种原因故意留下了漏洞。

他们表达了他们(对龙目岛安全)的担忧:

对内部程序的所有访问都将像以前一样可用,前提是 客户端应用程序显式地允许它,并承认它是 故意承担任何维护(或安全)问题,这可能 需要。 虽然Lombok可能认为他们在欺骗OpenJDK,但他们所做的一切 宣布他们有意欺骗自己的用户。

可能很快就会有一天,Lombok将无法围绕JDK的安全限制找到任何更具创造性的解决方案。即使他们这样做了,在您的项目中使用Lombok的安全性也可能存在问题。

更新18(22年5月11日)

最近的一条评论要求我做个总结,所以我把它放在了最上面。

简单的回答是,它使用起来非常安全,如果我们正在编写Java代码,我强烈建议使用它。

考虑到对JDK 17的支持已经有一段时间了,并且是在JDK正式发布后不到一个月才发布的,因此Lombok的安全性很高。如果需要,你可以随时去龙目岛。

作为一名顾问,我可以看到很多不同的公司是如何编写代码的。在过去的5年里,我的每个客户都使用龙目岛。这些都是财富1000强企业。它加快了开发速度,减少了出错的可能性。

也就是说,您仍然需要跟上JDK的最新特性。考虑使用Java record关键字使对象不可变,而不是使用某些Lombok特性。在有意义的地方使用Lombok。使用Lombok配置选项来防止以您不同意的方式使用它。

所以除非有重大的事情发生,这可能是我最后一次更新这个答案。谢谢你们的投票。我很高兴这有帮助。


我知道我迟到了,但我无法抗拒诱惑:喜欢Lombok的人也应该看看Scala。您在Lombok中发现的许多好想法都是Scala语言的一部分。

关于您的问题:让开发人员尝试Lombok肯定比尝试Scala更容易。试一试,如果他们喜欢,那就试试Scala。

免责声明:我也喜欢Java !


想要使用lombok的@ToString,但很快在Intellij IDEA中重新构建项目时遇到了随机编译错误。在增量编译成功完成之前,必须多次点击编译。

使用Intellij IDEA 12.1.6和13.0在jdk 1.6.0_39和1.6.0_45下尝试了lombok 1.12.2和0.9.3,没有任何lombok插件。

不得不手动从delomboked源复制生成的方法,并将lombok搁置,直到更好的时机。

更新

只有启用并行编译时才会出现这个问题。

提交一个问题: https://github.com/rzwitserloot/lombok/issues/648

更新

mplushnikov于2016年1月30日评论道: 更新版本的Intellij 不再有这样的问题了。我想这里可以关了。

更新

如果可能的话,我强烈建议从Java+Lombok切换到Kotlin。 因为它已经从头开始解决了Lombok试图解决的所有Java问题。


我还没有尝试使用Lombok -它是/是我清单上的下一个,但听起来Java 8给它带来了很大的问题,补救工作在一周前仍在进行中。我的来源是https://code.google.com/p/projectlombok/issues/detail?id=451。


我遇到了Lombok和Jackson CSV的问题,当我将我的对象(java bean)编组到CSV文件时,其中的列重复,然后我删除了Lombok的@Data注释,编组工作正常。


还有长期维护的风险。首先,我建议你阅读一下Lombok的实际工作原理,比如这里有一些来自开发人员的回答。

官方网站还列出了一些缺点,包括Reinier Zwitserloot的这句话:

It's a total hack. Using non-public API. Presumptuous casting (knowing that an annotation processor running in javac will get an instance of JavacAnnotationProcessor, which is the internal implementation of AnnotationProcessor (an interface), which so happens to have a couple of extra methods that are used to get at the live AST). On eclipse, it's arguably worse (and yet more robust) - a java agent is used to inject code into the eclipse grammar and parser class, which is of course entirely non-public API and totally off limits. If you could do what lombok does with standard API, I would have done it that way, but you can't. Still, for what its worth, I developed the eclipse plugin for eclipse v3.5 running on java 1.6, and without making any changes it worked on eclipse v3.4 running on java 1.5 as well, so it's not completely fragile.

总之,虽然Lombok可以节省一些开发时间,但如果有一个不向后兼容的javac更新(例如漏洞缓解),Lombok可能会让您陷入旧版本的Java,而开发人员则会争先恐后地更新他们对那些内部api的使用。这是否是一个严重的风险显然取决于项目。


龙目岛很棒,但是……

Lombok打破了注释处理的规则,因为它不生成新的源文件。这意味着它不能与其他注释处理器一起使用,如果它们期望getter /setter或其他任何存在的东西。

Annotation processing runs in a series of rounds. In each round, each one gets a turn to run. If any new java files are found after the round is completed, another round begins. In this way, the order of annotation processors doesn't matter if they only generate new files. Since lombok doesn't generate any new files, no new rounds are started so some AP that relies on lombok code don't run as expected. This was a huge source of pain for me while using mapstruct, and delombok-ing isn't a useful option since it destroys your line numbers in logs.

我最终破解了一个构建脚本,可以同时使用lombok和mapstruct。但我想放弃龙目岛,因为它太粗糙了——至少在这个项目中是这样。我一直在用龙目岛做其他东西。 更新到mapstruct+lombok:这两个库现在可以开箱即用。不过,对于其他注释处理器来说,这个问题仍然存在。


我对Lombok的看法是,它只是为编写样板Java代码提供了快捷方式。 当涉及到使用快捷方式来编写Java代码时,我会依赖IDE提供的这些特性——就像在Eclipse中一样,我们可以转到Source > Generate Getters and Setters菜单来生成getter和setter。 我不会依赖Lombok这样的库:

It pollutes your code with an indirection layer of alternative syntax (read @Getter, @Setter, etc. annotations). Rather than learning an alternative syntax for Java, I would switch to any other language that natively provides Lombok like syntax. Lombok requires the use of a Lombok supported IDE to work with your code. This dependency introduces a considerable risk for any non-trivial project. Does the open source Lombok project have enough resources to keep providing support for different versions of a wide range of Java IDE's available? Does the open source Lombok project have enough resources to keep providing support for newer versions of Java that will be coming in future? I also feel nervous that Lombok may introduce compatibility issues with widely used frameworks/libraries (like Spring, Hibernate, Jackson, JUnit, Mockito) that work with your byte code at runtime.

总而言之,我不喜欢用龙目岛来“调味”我的爪哇。


我读了一些关于龙目岛的意见,实际上我在一些项目中使用它。

嗯,第一次接触龙目岛时,我的印象很差。几周后,我开始喜欢上它了。但几个月后,我发现了很多使用它的小问题。所以,我对龙目岛的最终印象并不是那么积极。

我这么想的理由是:

IDE plugin dependency. The IDE support for Lombok is through plugins. Even working good in most part of the time, you are always a hostage from this plugins to be maintained in the future releases of the IDEs and even the language version (Java 10+ will accelerate the development of the language). For example, I tried to update from Intellij IDEA 2017.3 to 2018.1 and I couldn't do that because there was some problem on the actual lombok plugin version and I needed to wait the plugin be updated... This also is a problem if you would like to use a more alternative IDE that don't have any Lombok plugin support. 'Find usages' problem.. Using Lombok you don't see the generated getter, setter, constructor, builder methods and etc. So, if you are planning to find out where these methods are being used in your project by your IDE, you can't do this only looking for the class that owns this hidden methods. So easy that the developers don't care to break the encapsulation. I know that it's not really a problem from Lombok. But I saw a bigger tendency from the developers to not control anymore what methods needs to be visible or not. So, many times they are just copying and pasting @Getter @Setter @Builder @AllArgsConstructor @NoArgsConstructor annotations block without thinking what methods the class really need to be exposed. Builder Obssession ©. I invented this name (get off, Martin Fowler). Jokes apart, a Builder is so easy to create that even when a class have only two parameters the developers prefer to use @Builder instead of constructor or a static constructor method. Sometimes they even try to create a Builder inside the lombok Builder, creating weird situations like MyClass.builder().name("Name").build().create(). Barriers when refactoring. If you are using, for example, a @AllArgsConstructor and need to add one more parameter on the constructor, the IDE can't help you to add this extra parameter in all places (mostly, tests) that are instantiating the class. Mixing Lombok with concrete methods. You can't use Lombok in all scenarios to create a getter/setter/etc. So, you will see these two approaches mixed in your code. You get used to this after some time, but feels like a hack on the language.

就像另一个回答说的,如果您对Java的冗长感到愤怒,并使用Lombok来处理它,那么可以尝试Kotlin。