Kotlin reified 关键字
最后修改于 2025 年 4 月 19 日
Kotlin 的 reified
关键字解决了 Java 泛型函数中类型擦除的限制。 当与内联函数一起使用时,它会在运行时保留类型信息。 本教程通过实际例子深入探讨了 reified
。
基本定义
Kotlin 中的 reified
关键字与内联函数的类型参数一起使用。 它使类型信息在运行时可用,绕过 JVM 的类型擦除。 这使得类型检查和类型转换成为可能,而这些操作在使用泛型时是不可能的。
简单的 reified 函数
这个基本示例展示了如何创建一个带有 reified 类型参数的函数。 该函数可以在运行时检查实际类型。
package com.zetcode inline fun <reified T> checkType(obj: Any) { if (obj is T) { println("Object is of type ${T::class.simpleName}") } else { println("Object is NOT of type ${T::class.simpleName}") } } fun main() { checkType<String>("Kotlin") // Output: Object is of type String checkType<Int>("123") // Output: Object is NOT of type Int }
checkType
函数使用 reified 类型参数 T。它可以对 T 执行 is
检查并访问 T 的类信息。如果没有 reified,这是不可能的。
泛型类型检查
Reified 参数允许在泛型函数中进行运行时类型检查。 本示例演示了对集合进行类型安全过滤。
package com.zetcode inline fun <reified T> filterByType(list: List<Any>): List<T> { return list.filter { it is T }.map { it as T } } fun main() { val mixedList = listOf(1, "Two", 3, "Four", 5.0) val strings = filterByType<String>(mixedList) println(strings) // Output: [Two, Four] }
filterByType
函数过滤一个列表,仅保留类型为 T 的元素。 reified 参数同时启用类型检查和安全类型转换。 这提供了类型安全的集合操作。
创建泛型类型的实例
使用 reified 类型,您可以在运行时创建泛型类型的新实例。 此示例展示了如何实现一个泛型工厂函数。
package com.zetcode inline fun <reified T : Any> createInstance(): T { return T::class.constructors.first().call() } class Person(val name: String = "Unknown") fun main() { val person = createInstance<Person>() println(person.name) // Output: Unknown }
createInstance
函数使用反射创建类型 T 的新实例。 reified 参数提供对 T 的类对象的访问。 请注意,该类必须有一个无参数构造函数。
使用 reified 进行 JSON 解析
Reified 类型对于 JSON 解析特别有用。 此示例显示了一个类型安全的 JSON 反序列化器。
package com.zetcode import com.google.gson.Gson inline fun <reified T> fromJson(json: String): T { return Gson().fromJson(json, T::class.java) } data class User(val name: String, val age: Int) fun main() { val json = """{"name":"Alice","age":30}""" val user = fromJson<User>(json) println(user) // Output: User(name=Alice, age=30) }
fromJson
函数使用 Gson 将 JSON 反序列化为指定类型。 reified 参数提供了 Gson 所需的 Class 对象。 这创建了一个类型安全的 JSON 解析实用程序。
使用 reified 进行依赖注入
Reified 类型通过消除传递 Class 对象的需要来简化依赖注入。 此示例演示了一个简单的 DI 容器。
package com.zetcode class ServiceLocator { private val services = mutableMapOf<Class<*>, Any>() fun <T : Any> register(service: T) { services[service::class.java] = service } inline fun <reified T : Any> resolve(): T { return services[T::class.java] as T } } interface Logger { fun log(message: String) } class ConsoleLogger : Logger { override fun log(message: String) = println(message) } fun main() { val locator = ServiceLocator() locator.register(ConsoleLogger()) val logger = locator.resolve<Logger>() logger.log("Hello DI!") // Output: Hello DI! }
resolve
函数使用 reified 类型参数来查找服务。 这消除了传递 Class 对象的需要,同时保持了类型安全。 API 变得更简洁、更直观。
Android Intent 扩展
在 Android 开发中,reified 类型简化了 Intent 处理。 此示例显示了一种类型安全的方式来启动活动。
package com.zetcode import android.content.Context import android.content.Intent inline fun <reified T : Any> Context.startActivity() { startActivity(Intent(this, T::class.java)) } // Example Activity class class MainActivity : AppCompatActivity() // Usage in another Activity: // startActivity<MainActivity>()
startActivity
扩展函数使用 reified 类型参数创建 Intent。 这取代了冗长的 Intent(this, MainActivity::class.java)
模式。 代码变得更简洁、类型更安全。
类型安全的适配器模式
Reified 类型支持类型安全的适配器实现。 此示例展示了一个用于不同数据类型的泛型适配器。
package com.zetcode interface Adapter<T> { fun adapt(data: String): T } inline fun <reified T> getAdapter(): Adapter<T> { return when (T::class) { Int::class -> object : Adapter<Int> { override fun adapt(data: String) = data.toInt() } String::class -> object : Adapter<String> { override fun adapt(data: String) = data } else -> throw IllegalArgumentException("No adapter for ${T::class}") } } fun main() { val intAdapter = getAdapter<Int>() println(intAdapter.adapt("123")) // Output: 123 val stringAdapter = getAdapter<String>() println(stringAdapter.adapt("Hello")) // Output: Hello }
getAdapter
函数根据 reified 类型参数返回一个合适的适配器。 这创建了一个类型安全的工厂模式,而无需显式类型标记。 适配器在编译时解析。
reified 的最佳实践
- 与内联函数一起使用: reified 仅适用于内联函数,因为类型信息在编译时被保留。
- 限制范围: 仅在您真正需要运行时类型信息以避免不必要的函数内联时使用 reified。
- 与泛型结合使用: reified 在处理泛型类型时表现出色,否则这些类型会受到类型擦除的影响。
- 考虑性能: 内联带有 reified 类型的大型函数可能会增加代码大小。
- 用于类型安全的 API: reified 实现了更简洁、类型安全的 API,用于 JSON 解析、DI 和其他模式。
来源
本教程深入探讨了 Kotlin 的 reified
关键字,展示了它如何解决类型擦除问题。 我们探讨了实际示例,包括 JSON 解析、依赖注入和 Android 开发。 正确使用 reified 类型可以使您的泛型代码更具类型安全性和表现力。
作者
列出 所有 Kotlin 教程。