KotlinPoet 详解
KotlinPoet 是一个强大的 Kotlin 代码生成库,由 Square 公司开发。它提供了简洁的 API 来生成 Kotlin 源代码文件。
核心概念
1. 基本组件
scss
// 添加依赖
implementation("com.squareup:kotlinpoet:1.14.2")
2. 主要类介绍
- FileSpec: 表示整个 .kt 文件
- TypeSpec: 表示类、接口、对象等类型
- FunSpec: 表示函数
- PropertySpec: 表示属性
- ParameterSpec: 表示参数
基础用法
生成简单的类
css
import com.squareup.kotlinpoet.*
fun main() {
val personClass = TypeSpec.classBuilder("Person")
.addProperty(
PropertySpec.builder("name", String::class)
.initializer("%S", "John Doe")
.build()
)
.addProperty(
PropertySpec.builder("age", Int::class)
.initializer("25")
.build()
)
.addFunction(
FunSpec.builder("greet")
.addStatement("println(%S)", "Hello, I'm $name")
.build()
)
.build()
val file = FileSpec.builder("com.example", "Person")
.addType(personClass)
.build()
file.writeTo(System.out)
}
输出结果:
kotlin
package com.example
class Person {
val name: String = "John Doe"
val age: Int = 25
fun greet() {
println("Hello, I'm $name")
}
}
生成函数
php
val function = FunSpec.builder("calculateSum")
.addParameter("a", Int::class)
.addParameter("b", Int::class)
.returns(Int::class)
.addStatement("return a + b")
.build()
val file = FileSpec.builder("com.example", "MathUtils")
.addFunction(function)
.build()
高级特性
1. 注解支持
less
val personClass = TypeSpec.classBuilder("Person")
.addAnnotation(
AnnotationSpec.builder(Serializable::class).build()
)
.addProperty(
PropertySpec.builder("name", String::class)
.addAnnotation(
AnnotationSpec.builder(JsonProperty::class)
.addMember("%S", "full_name")
.build()
)
.build()
)
.build()
2. 泛型支持
less
val listClass = TypeSpec.classBuilder("Repository")
.addTypeVariable(TypeVariableName("T"))
.addFunction(
FunSpec.builder("save")
.addParameter("item", TypeVariableName("T"))
.build()
)
.build()
3. 扩展函数
arduino
val extensionFunction = FunSpec.builder("toJson")
.receiver(String::class)
.returns(String::class)
.addStatement("return %T.encodeToString(this)", Json::class)
.build()
4. 数据类生成
less
val dataClass = TypeSpec.classBuilder("User")
.primaryConstructor(
FunSpec.constructorBuilder()
.addParameter("id", Long::class)
.addParameter("username", String::class)
.addParameter("email", String::class)
.build()
)
.addProperty(
PropertySpec.builder("id", Long::class)
.initializer("id")
.build()
)
.addProperty(
PropertySpec.builder("username", String::class)
.initializer("username")
.build()
)
.addProperty(
PropertySpec.builder("email", String::class)
.initializer("email")
.build()
)
.addModifiers(KModifier.DATA)
.build()
实际应用示例
1. 生成 Builder 模式
css
fun createBuilderClass() {
val builderClass = TypeSpec.classBuilder("PersonBuilder")
.addProperty(
PropertySpec.builder("name", String::class)
.mutable(true)
.initializer("%S", "")
.build()
)
.addProperty(
PropertySpec.builder("age", Int::class)
.mutable(true)
.initializer("0")
.build()
)
.addFunction(
FunSpec.builder("setName")
.addParameter("name", String::class)
.addStatement("this.name = name")
.addStatement("return this")
.returns(ClassName("", "PersonBuilder"))
.build()
)
.addFunction(
FunSpec.builder("build")
.addStatement("return Person(name, age)")
.returns(ClassName("", "Person"))
.build()
)
.build()
FileSpec.builder("com.example", "PersonBuilder")
.addType(builderClass)
.build()
.writeTo(System.out)
}
2. 生成 Retrofit 接口
less
fun createApiInterface() {
val apiInterface = TypeSpec.interfaceBuilder("UserApi")
.addFunction(
FunSpec.builder("getUser")
.addAnnotation(
AnnotationSpec.builder(GET::class)
.addMember("%S", "/users/{id}")
.build()
)
.addParameter(
ParameterSpec.builder("id", Long::class)
.addAnnotation(AnnotationSpec.builder(Path::class)
.addMember("%S", "id")
.build()
)
.build()
)
.returns(ClassName("retrofit2", "Call<User>"))
.build()
)
.build()
FileSpec.builder("com.example.api", "UserApi")
.addType(apiInterface)
.build()
.writeTo(System.out)
}
代码格式化与控制
1. 控制缩进和格式
ini
val file = FileSpec.builder("com.example", "Example")
.addType(/* ... */)
.build()
// 写入文件时控制格式
file.writeTo(
path = Paths.get("src/main/kotlin"),
charset = Charsets.UTF_8,
// 可以传递自定义的 CodeWriter 来控制格式
)
2. 使用 % 占位符
KotlinPoet 使用百分比符号作为占位符:
perl
FunSpec.builder("printMessage")
.addParameter("message", String::class)
.addStatement("println(%P)", "Message: $message") // %P 用于字符串字面量
.addStatement("val result = %L + %L", "a", "b") // %L 用于字面值
.addStatement("val type = %T::class", String::class) // %T 用于类型
.build()
最佳实践
- 模块化生成: 将代码生成逻辑分解为小的可重用函数
- 使用模板: 对于复杂结构,考虑使用模板模式
- 错误处理: 添加适当的验证和错误处理
- 代码质量: 生成的代码应该遵循 Kotlin 编码规范
常见用例
- 序列化/反序列化代码生成
- API 客户端生成
- 数据库访问层生成
- 测试代码生成
- DSL 生成
KotlinPoet 是一个功能强大的工具,特别适合在需要动态生成 Kotlin 代码的场景中使用,如注解处理器、代码生成工具等。