Kotlin无法识别Java Lombok的访问器?

94

使用 Kotlin 1.0.0 版本(在 IntelliJ 15 中编译)。

println(myPojoInstance.foo)
当尝试编译引用了Lombok基于POJO的代码(在IntelliJ或Gradle中)时,会出现错误:“无法访问'MyPojo'中的'foo':它是'private'的”。这是真的,它们都是私有的,而我的对象具有@Value @Builder的lombok注释。
我尝试过专门调用getFoo(),但它显示“无法解析的getFoo参考”。也许有一些技巧可以让Kotlin知道如何处理lombok注释?

1
你使用了 kapt 吗?http://blog.jetbrains.com/kotlin/2015/06/better-annotation-processing-supporting-stubs-in-kapt/ - voddan
正如@voddan所指出的那样,您没有提供足够的信息来解决这个问题。此外,如果您尝试了Kapt,它是在一个模块内还是多个模块内? - Jayson Minard
3
直到提到"kapt"之前,我并不知道有什么可用的方法来解决它。我多次阅读了JetBrains页面上的“java-interop”,但找不到任何提示如何处理它的线索。在编辑器中,IntelliJ没有将其标记为错误,但是无论是在IntelliJ中编译还是通过JetBrains Kotlin Gradle插件使用Gradle编译都无法正常工作。 - Chris Kessel
3
你解决了kapt的问题了吗?我很感兴趣知道。 - Vojtěch
5个回答

94

通常情况下,不会。这种行为的原因是Lombok是javac的注解处理器,但是当kotlin编译器运行时,它也使用javac,但没有注解处理,因此kotlin看不到尚未生成的声明。

目前唯一的解决方法是定义严格的编译顺序:先编译Java,再编译kotlin。不幸的是,这种方法有一个很大的缺点:在这种情况下,您无法从Java中使用Kotlin代码。要解决此问题,您可能需要多模块项目,这可能会带来很多麻烦。


2
哎呀,真倒霉。是的,我在我的程序中间拿了一块Java代码并将其迁移到Kotlin,特别是为了看看Java->Kotlin->Java支持将如何工作。目标是逐步迁移代码。然而,我们在所有领域POJO中都大量使用Lombok。也许我可以在编译Java之前搞一个"compilePOJOs"目标来运行。 - Chris Kessel
2
Sergey,JetBrains有关于Kotlin如何查看同一模块中的Java代码(共存)的链接/常见问题解答吗?Gradle在编译Java之前会先编译Kotlin,但显然Kotlin知道Java代码(除了注释预处理之外)。Kotlin编译器是否在编译.kt文件之前扫描Java代码? - Chris Kessel
2
你并不孤单,我们有Spring Roo生成的POJO,而Kotlin也因为Sergey所说的同样原因无法看到它们。 - fasth
33
对我们来说,这是一个真正的难题。我们想在那些大量依赖lombok数据类和构建器的应用中引入Kotlin。虽然可以简单地将其视为“我说过不要使用lombok...”,但事实仍然是,这会阻止许多人考虑使用Kotlin。 - Billybong
3
可能会有帮助的一个方法是使用DeLombok工具:https://projectlombok.org/features/delombok.html。通过使用DeLombok,您可以在源代码中生成由Lombok生成的Java代码,然后就可以将Lombok从项目中删除了。 - Pedro Hidalgo

21

有一个Kotlin编译器插件支持lombok。它仍处于实验阶段,可以与GradleMaven一起使用。

它只支持少量的注解,包括:

  • @Getter@Setter
  • @NoArgsConstructor@RequiredArgsConstructor@AllArgsConstructor
  • @Data
  • @With
  • @Value

看起来能够正常工作。不幸的是,它们不支持@Builder 注解,但你可以在YouTrack上提出请求添加。

有关更多信息,请参见kotlin文档中的Lombok编译器插件

更新 1

上面提到的@Builder 注解问题已经得到解决!修复的目标版本是1.8.0-Beta


6
补充Sergey Mashkov的回答(我没有足够的声望在评论中添加),这里有一个Gradle多项目设置的示例应用程序,其中Kotlin可以看到由Lombok生成的代码(无需kapt或delomboking)。但是要注意,Kotlin可以调用Java代码,但Java不能调用该特定模块中的Kotlin代码(因为这会创建循环依赖关系)。如果您拥有现有的Java代码库,并且所有新代码都是用Kotlin编写的,则此类构建可能非常适合您。
然而,我希望完全支持Lombok/Kotlin。虽然Kotlin与Java完全可互操作,但现实情况是Lombok被广泛使用,这个问题可能会阻止许多想要转换到Kotlin的开发人员这样做。

6

正如上面的评论中提到的那样,delombok是有帮助的。 在maven构建的情况下,可以这样做:

<plugin>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-maven-plugin</artifactId>
    <version>${lombok.version}.0</version>
    <executions>
        <execution>
            <id>delombok</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>delombok</goal>
            </goals>
            <configuration>
                <formatPreferences>
                    <javaLangAsFQN>skip</javaLangAsFQN>
                </formatPreferences>
                <verbose>true</verbose>
            </configuration>
        </execution>
        <execution>
            <id>test-delombok</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>testDelombok</goal>
            </goals>
            <configuration>
                <verbose>true</verbose>
            </configuration>
        </execution>
    </executions>
</plugin>

3

根据官方文档,如果您使用delombok并在build > plugins > plugin > kotlin-maven-plugin的pom.xml下添加target/generated-sources/delombok文件夹,则看起来会起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接