1. 概述

Lombok 是一个为 Java 设计的流行库,旨在消除大量样板代码。例如,通过 Lombok,我们无需手动编写 getter、setter、toString()equals()hashCode() 等方法。

虽然 Kotlin 本身已经具备类似能力,但在混合使用 Java 和 Kotlin 的项目中,我们仍可能需要让 Kotlin 代码调用那些使用了 Lombok 注解的 Java 类。✅

本文将介绍如何在 Kotlin 项目中启用 Lombok,并说明哪些功能可用,以及常见的集成方式和注意事项。

⚠️ 重点提醒:Lombok 只能作用于 Java 类,无法直接用于 Kotlin 类。不要试图在 .kt 文件中使用 @Data 或其他 Lombok 注解,这不会生效。

2. 在 Kotlin 中配置 Lombok

Kotlin 官方提供了 kotlin-lombok-plugin 插件,允许我们在项目中处理带有 Lombok 注解的 Java 类。该插件支持 Gradle、Maven 构建工具,并兼容 kapt(Kotlin Annotation Processing Tool)。

2.1. Gradle 配置

build.gradle.kts 中添加插件声明:

plugins {
    kotlin("plugin.lombok") version "1.8.10"
    id("io.freefair.lombok") version "5.3.0"
}

✅ 推荐同时使用 freefair/lombok plugin,它能自动管理 Lombok 依赖和注解处理器。

2.2. Maven 配置

pom.xml 中配置 Kotlin 编译器插件及其依赖:

<plugin>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-plugin</artifactId>
    <version>1.8.10</version>
    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-lombok</artifactId>
            <version>1.8.20-RC</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</plugin>

这样就能确保编译期正确处理 Lombok 生成的代码。

2.3. 配合 kapt 使用

kapt 默认会禁用 javac 的注解处理器,而 Lombok 正是基于 javac 实现的。因此必须显式开启对原生注解处理器的支持。

Gradle 配置:

kapt {
    keepJavacAnnotationProcessors = true
}

Maven 配置:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.5.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <annotationProcessorPaths>
            <annotationProcessorPath>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.20</version> 
            </annotationProcessorPath>
        </annotationProcessorPaths>
    </configuration>
</plugin>

❌ 踩坑提示:如果不设置 keepJavacAnnotationProcessors = true,Lombok 注解将不生效,导致编译报错或运行时字段访问异常。

2.4. 命令行方式

如果你直接使用 kotlinc 编译,可以通过 -Xplugin 参数加载 Lombok 插件 JAR:

-Xplugin=$KOTLIN_HOME/lib/lombok-compiler-plugin.jar

该 JAR 包包含在 Kotlin 编译器的二进制发行版中,适用于脚本化构建场景。

3. 为什么要在 Kotlin 项目中用 Lombok?

Kotlin 语言本身已经内置了许多“消除样板代码”的特性,比如:

  • data class 自动生成 toString()equals()hashCode()copy()
  • 属性默认提供 getter/setter
  • 主构造函数参数可直接声明为 val / var

对比示例:

Java + Lombok:

@Data
public class Person { 
    private String name; 
    private int age; 
}

等价的 Kotlin 写法:

data class Person(val name: String, val age: Int)

两者语义几乎一致。

那么问题来了:既然 Kotlin 更简洁,为何还要引入 Lombok?

答案很现实:项目是渐进迁移的。很多老系统是 Java 写的,用了大量 Lombok 注解。当你开始用 Kotlin 编写新模块时,仍然要调用这些旧的 Java 类。

✅ 所以 kotlin-lombok-plugin 的核心用途是:让 Kotlin 代码能无缝调用使用了 Lombok 的 Java 类,避免重写已有逻辑。

4. 支持的 Lombok 注解及使用方式

Kotlin Lombok 插件支持大部分常用注解,以下是关键列表:

4.1. 支持的注解类型

注解 说明
@NoArgsConstructor 生成无参构造函数
@AllArgsConstructor 生成全参构造函数
@RequiredArgsConstructor final 字段生成构造函数
@Getter / @Setter 生成属性的 getter/setter 方法
@ToString 自动生成 toString() 输出所有字段
@EqualsAndHashCode 自动生成 equals()hashCode()
@Data 组合注解:相当于 @ToString + @EqualsAndHashCode + @Getter + @Setter + @RequiredArgsConstructor
@Value 类似 @Data,但生成不可变类(所有字段 private final,无 setter)
@With 创建不可变对象的变体,返回修改某一字段后的新实例

⚠️ 注意:这些注解只能加在 .java 文件上,不能用于 .kt 文件。

4.2. 示例:使用 @Getter@Setter@EqualsAndHashCode

定义一个 Java 类:

@Getter
@Setter
@EqualsAndHashCode
public class Person {
    private String name;
    private int age;
    private String gender;
    private int id;
}

在 Kotlin 中可以直接使用其生成的方法:

val p = Person()
p.name = "Nappy"
p.age = 20
p.gender = "Male"

val p1 = Person()
p1.name = "Nappy"
p1.age = 20
p1.gender = "Male"

assertEquals("Nappy", p.name)
assertEquals(20, p.age)
assertEquals("Male", p.gender)

assertEquals(p, p1)
assertEquals(p.hashCode(), p1.hashCode())

✅ 虽然是 Kotlin 代码,但成功调用了由 Lombok 生成的 getter、setter、equalshashCode 方法。

4.3. 示例:使用 @ToString@AllArgsConstructor

Java 类定义:

@AllArgsConstructor
@ToString
public class Person1 {
    private String name;
    private int age;
    private String gender;
    private int id;
}

Kotlin 调用:

val person = Person1("Nappy", 20, "Male", 1)
assertEquals("Person1(name=Nappy, age=20, gender=Male, id=1)", person.toString())

可以看到 @AllArgsConstructor 提供了便捷的构造方式,@ToString 输出格式清晰,便于调试。

5. 总结

  • Lombok 不能用于 Kotlin 类,仅用于支持 Kotlin 对带 Lombok 注解的 Java 类的调用。
  • 必须正确配置插件(Gradle/Maven),并注意 启用 javac 注解处理器(尤其是配合 kapt 时)。
  • 支持主流 Lombok 注解,如 @Data@Value@ToString@EqualsAndHashCode 等。
  • 典型应用场景是 Java/Kotlin 混合项目,无需立即重写旧代码即可平滑过渡。

📌 建议:对于新模块,优先使用 Kotlin 自身特性(如 data class);对于存量 Java 类,可通过插件继续使用 Lombok,减少迁移成本。


原始标题:Using Lombok With Kotlin