1. 简介
本文将介绍 KotlinPoet,一个用于生成 Kotlin 源代码的开源库。我们会了解它的基本用途、能生成的代码类型,以及如何在项目中使用它。
KotlinPoet 是 Square 公司开发的 JavaPoet 的 Kotlin 版本。如果你熟悉 JavaPoet,那么 KotlinPoet 的使用方式会非常类似。
2. KotlinPoet 是什么?
KotlinPoet 是一个用于生成 Kotlin 源码的库,由 Square 维护。它与 JavaPoet 类似,但专注于 Kotlin。
不同于 ASM 这类直接操作字节码的工具,KotlinPoet 生成的是原始的、未编译的 Kotlin 源码。这意味着生成的代码需要先编译,才能运行。但在某些场景下,这种机制反而更灵活,比如构建时代码生成、IDE 插件开发等。
它可以生成 Kotlin 中常见的各种结构:类、函数、属性、注解等。这意味着你可以用它来生成一行代码,也可以生成整个 Kotlin 文件。
3. 依赖配置
使用 KotlinPoet 前,需要在项目中引入依赖。截至本文撰写时,最新版本为 1.16.0。
Maven 配置:
<dependency>
<groupId>com.squareup</groupId>
<artifactId>kotlinpoet-jvm</artifactId>
<version>1.16.0</version>
</dependency>
Gradle 配置:
implementation("com.squareup:kotlinpoet:1.16.0")
引入依赖后即可开始使用 KotlinPoet。
4. 生成代码的基本方式
KotlinPoet 通过一系列 Spec 类来生成代码。每个 Spec 对应一种代码结构:
TypeSpec
:类、接口、对象等类型定义FunSpec
:函数定义PropertySpec
:属性定义FileSpec
:整个 Kotlin 文件
这些类都提供了 builder 模式用于构建代码结构。
例如,生成一个空类:
val code = TypeSpec.classBuilder("Test").build()
生成的代码如下:
public class Test
调用 toString()
即可获取生成的代码字符串。
5. 生成函数
生成函数是 KotlinPoet 的核心功能之一。可以生成函数签名、参数、返回值和函数体。
使用 FunSpec
构建函数:
FunSpec.builder("simple") // public fun simple() {}
FunSpec.constructorBuilder() // public constructor()
FunSpec.getterBuilder() // public get() {}
FunSpec.setterBuilder() // public set() {}
5.1. 函数体的构建
函数体使用 addStatement()
添加:
val code = FunSpec.builder("test")
.addStatement("println(\"Testing\")")
.build()
生成代码如下:
public fun test() {
println("Testing")
}
你也可以使用格式化字符串简化字符串拼接:
val code = FunSpec.builder("test")
.addStatement("println(%S)", "Testing")
.build()
✅ 常用格式化参数说明:
格式符 | 含义 |
---|---|
%S |
字符串,自动加引号并转义 |
%P |
字符串模板,加引号但不转义 $ |
%L |
字面量,直接插入 |
%N |
其他代码元素,插入其名称 |
%T |
类型,自动导入并插入 |
%M |
包/类成员,自动处理引用和导入 |
5.2. 控制流结构
生成 if、for 等控制结构时,使用 beginControlFlow()
和 endControlFlow()
:
val code = FunSpec.builder("test")
.beginControlFlow("if (showOutput)")
.addStatement("println(%S)", "Testing")
.endControlFlow()
.build()
生成代码如下:
public fun test() {
if (showOutput) {
println("Testing")
}
}
你还可以使用 nextControlFlow()
来添加 else if
或 else
分支。
5.3. 参数设置
使用 addParameter()
添加函数参数:
val code = FunSpec.builder("test")
.addParameter("param", String::class)
.build()
生成:
public fun test(param: kotlin.String) {
}
你也可以为参数指定默认值:
.addParameter(ParameterSpec.builder("param", Int::class).defaultValue("%L", 42).build())
5.4. 返回值类型
使用 returns()
设置返回类型:
val code = FunSpec.builder("test")
.returns(String::class)
.build()
生成:
public fun test(): kotlin.String {
}
如果函数只有一行 return
语句,KotlinPoet 会自动使用单表达式函数语法:
.addStatement("return 5")
.returns(Int::class)
生成:
public fun test(): kotlin.Int = 5
6. 生成类型定义
除了函数,KotlinPoet 也支持生成类、接口、对象、枚举等类型。
使用 TypeSpec
构建类型:
TypeSpec.classBuilder("Test") // public class Test
TypeSpec.interfaceBuilder("Test") // public interface Test
TypeSpec.objectBuilder("Test") // public object Test
TypeSpec.enumBuilder("Test") // public enum class Test
6.1. 添加方法
使用 addFunction()
向类中添加方法:
val code = TypeSpec.classBuilder("Test")
.addFunction(FunSpec.builder("doSomething")
.returns(Int::class)
.addParameter("input", String::class)
.build())
.build()
生成:
public class Test {
public fun doSomething(input: kotlin.String): kotlin.Int {
}
}
6.2. 设置访问修饰符
使用 addModifiers()
设置访问修饰符或其它修饰符(如 abstract
、final
):
.addFunction(FunSpec.builder("doSomething")
.addModifiers(KModifier.PROTECTED, KModifier.ABSTRACT)
.build())
⚠️ 注意:KotlinPoet 不会阻止你设置逻辑冲突的修饰符组合,比如 final
和 abstract
同时存在。这类逻辑错误需开发者自行注意。
6.3. 添加属性
使用 PropertySpec
添加类属性:
.addProperty(PropertySpec.builder("test", String::class)
.addModifiers(KModifier.PRIVATE)
.mutable()
.initializer("%S", "Hello")
.build())
生成:
private var test: kotlin.String = "Hello"
也可以简化为:
.addProperty("test", String::class)
7. 生成完整 Kotlin 文件
最后,我们来看看如何生成一个完整的 .kt
文件。
使用 FileSpec
构建文件:
val code = FileSpec.builder("com.baeldung.kotlin.kotlinpoet", "Testing.kt").build()
生成:
package com.baeldung.kotlin.kotlinpoet
你可以继续添加类、函数、属性等:
val code = FileSpec.builder("com.baeldung.kotlin.kotlinpoet", "Testing.kt")
.addType(TypeSpec.classBuilder("Testing")
.addFunction(FunSpec.builder("count")
.returns(Int::class)
.addParameter(ParameterSpec.builder("items", List::class).build())
.addStatement("return items.size()")
.build())
.build())
.build()
生成:
package com.baeldung.kotlin.kotlinpoet
import kotlin.Int
import kotlin.collections.List
public class Testing {
public fun count(items: List): Int = items.size()
}
✅ KotlinPoet 会自动添加必要的 import 语句,并省略全限定类名。
8. 总结
KotlinPoet 是一个功能强大、使用灵活的代码生成工具。它可以帮助你自动化生成 Kotlin 代码,适用于构建插件、代码模板生成、DSL 构建等场景。
虽然本文只介绍了它的基础用法,但它的能力远不止这些。建议你尝试在自己的项目中集成并使用它。
所有示例代码都可以在 GitHub 上找到:GitHub 示例地址 ✅