ZetCode

Kotlin reified 关键字

最后修改于 2025 年 4 月 19 日

Kotlin 的 reified 关键字解决了 Java 泛型函数中类型擦除的限制。 当与内联函数一起使用时,它会在运行时保留类型信息。 本教程通过实际例子深入探讨了 reified

基本定义

Kotlin 中的 reified 关键字与内联函数的类型参数一起使用。 它使类型信息在运行时可用,绕过 JVM 的类型擦除。 这使得类型检查和类型转换成为可能,而这些操作在使用泛型时是不可能的。

简单的 reified 函数

这个基本示例展示了如何创建一个带有 reified 类型参数的函数。 该函数可以在运行时检查实际类型。

SimpleReified.kt
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 参数允许在泛型函数中进行运行时类型检查。 本示例演示了对集合进行类型安全过滤。

TypeCheck.kt
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 类型,您可以在运行时创建泛型类型的新实例。 此示例展示了如何实现一个泛型工厂函数。

InstanceCreation.kt
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 反序列化器。

JsonParser.kt
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 容器。

DependencyInjection.kt
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 处理。 此示例显示了一种类型安全的方式来启动活动。

AndroidIntent.kt
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 类型支持类型安全的适配器实现。 此示例展示了一个用于不同数据类型的泛型适配器。

AdapterPattern.kt
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 的最佳实践

来源

Kotlin reified 类型参数文档

本教程深入探讨了 Kotlin 的 reified 关键字,展示了它如何解决类型擦除问题。 我们探讨了实际示例,包括 JSON 解析、依赖注入和 Android 开发。 正确使用 reified 类型可以使您的泛型代码更具类型安全性和表现力。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有多年的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我撰写了 1400 多篇文章和 8 本电子书。 我有超过八年的编程教学经验。

列出 所有 Kotlin 教程