KotlinPoet 详解

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()

最佳实践

  1. 模块化生成: 将代码生成逻辑分解为小的可重用函数
  2. 使用模板: 对于复杂结构,考虑使用模板模式
  3. 错误处理: 添加适当的验证和错误处理
  4. 代码质量: 生成的代码应该遵循 Kotlin 编码规范

常见用例

  • 序列化/反序列化代码生成
  • API 客户端生成
  • 数据库访问层生成
  • 测试代码生成
  • DSL 生成

KotlinPoet 是一个功能强大的工具,特别适合在需要动态生成 Kotlin 代码的场景中使用,如注解处理器、代码生成工具等。

相关推荐
洛小豆5 小时前
Git打标签仓库看不到?她说:豆子,你又忘了加 --tags!
git·后端·github
不老刘5 小时前
GitHub Spec-Kit:AI 时代的规范驱动开发工具
人工智能·github·spec-kit
piggy侠6 小时前
【GitHub每日速递 251016】23k star,Daytona:90ms内极速运行AI代码,安全弹性基础设施来袭!
算法·github
CoderJia程序员甲7 小时前
GitHub 热榜项目 - 日榜(2025-10-15)
ai·开源·大模型·github·ai教程
绝无仅有8 小时前
面试真实经历某商银行大厂Java问题和答案总结(四)
后端·面试·github
绝无仅有8 小时前
面试真实经历某商银行大厂Java问题和答案总结(六)
后端·面试·github
xurime8 小时前
Excelize 开源基础库发布 2.10.0 版本更新
golang·开源·github·excel·ai编程·go语言
CoderJia程序员甲17 小时前
GitHub 热榜项目 - 日榜(2025-10-11)
ai·开源·github·ai编程·github热榜
CoderJia程序员甲21 小时前
GitHub 热榜项目 - 日榜(2025-10-14)
ai·开源·大模型·github·ai教程