跳到内容

%T 用于类型

KotlinPoet 内置了对类型的丰富支持,包括自动生成 import 语句。只需使用 %T 来引用类型即可。

val today = FunSpec.builder("today")
  .returns(Date::class)
  .addStatement("return %T()", Date::class)
  .build()

val helloWorld = TypeSpec.classBuilder("HelloWorld")
  .addFunction(today)
  .build()

val kotlinFile = FileSpec.builder("com.example.helloworld", "HelloWorld")
  .addType(helloWorld)
  .build()

kotlinFile.writeTo(System.out)

这将生成以下 .kt 文件,其中包含必要的 import 语句

package com.example.helloworld

import java.util.Date

class HelloWorld {
  fun today(): Date = Date()
}

我们将 Date::class 传递进去,以引用一个恰好在我们生成代码时可用的类。但这并非必须如此。这里有一个类似的例子,但它引用了一个(尚)不存在的类

val hoverboard = ClassName("com.mattel", "Hoverboard")

val tomorrow = FunSpec.builder("tomorrow")
  .returns(hoverboard)
  .addStatement("return %T()", hoverboard)
  .build()

那个尚不存在的类同样会被导入

package com.example.helloworld

import com.mattel.Hoverboard

class HelloWorld {
  fun tomorrow(): Hoverboard = Hoverboard()
}

ClassName 类型非常重要,在使用 KotlinPoet 时你会经常用到它。它可以识别任何声明过的类。声明类型只是 Kotlin 丰富类型系统的开端:我们还有数组、参数化类型、通配符类型、lambda 类型和类型变量。KotlinPoet 为构建所有这些类型提供了相应的类

import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.STAR

val hoverboard = ClassName("com.mattel", "Hoverboard")
val list = ClassName("kotlin.collections", "List")
val arrayList = ClassName("kotlin.collections", "ArrayList")
val listOfHoverboards = list.parameterizedBy(hoverboard)
val arrayListOfHoverboards = arrayList.parameterizedBy(hoverboard)

val thing = ClassName("com.misc", "Thing")
val array = ClassName("kotlin", "Array")
val producerArrayOfThings = array.parameterizedBy(WildcardTypeName.producerOf(thing))

val beyond = FunSpec.builder("beyond")
  .returns(listOfHoverboards)
  .addStatement("val result = %T()", arrayListOfHoverboards)
  .addStatement("result += %T()", hoverboard)
  .addStatement("result += %T()", hoverboard)
  .addStatement("result += %T()", hoverboard)
  .addStatement("return result")
  .build()

val printThings = FunSpec.builder("printThings")
  .addParameter("things", producerArrayOfThings)
  .addStatement("println(things)")
  .build()

val printKClass = FunSpec.builder("printKClass")
  .addParameter("kClass", KClass::class.asClassName().parameterizedBy(STAR))
  .addStatement("println(kClass)")
  .build()

STAR 在 KotlinPoet 中表示为 *。你可以在 KDoc 中找到更多信息。

KotlinPoet 会分解每种类型,并在可能的情况下导入其组件。

package com.example.helloworld

import com.mattel.Hoverboard
import com.misc.Thing
import kotlin.Array
import kotlin.collections.ArrayList
import kotlin.collections.List
import kotlin.reflect.KClass

class HelloWorld {
  fun beyond(): List<Hoverboard> {
    val result = ArrayList<Hoverboard>()
    result += Hoverboard()
    result += Hoverboard()
    result += Hoverboard()
    return result
  }

  fun printThings(things: Array<out Thing>) {
    println(things)
  }

  fun printKClass(kClass: KClass<*>) {
    println(kClass)
  }
}

可空类型

KotlinPoet 支持可空类型。要将 TypeName 转换为其对应的可空类型,请使用 copy() 方法,并将 nullable 参数设置为 true

val java = PropertySpec.builder("java", String::class.asTypeName().copy(nullable = true))
  .mutable()
  .addModifiers(KModifier.PRIVATE)
  .initializer("null")
  .build()

val helloWorld = TypeSpec.classBuilder("HelloWorld")
  .addProperty(java)
  .addProperty("kotlin", String::class, KModifier.PRIVATE)
  .build()

生成

class HelloWorld {
  private var java: String? = null

  private val kotlin: String
}