我试图理解 reified
关键字的用途,显然是 it's allowing us to do reflection on generics .
但是,当我将其省略时,它也可以正常工作。任何人愿意解释这何时会产生实际的不同?
最佳答案
TL;DR:什么是 reified
适合
fun <T> myGenericFun(c: Class<T>)
在泛型函数的主体中,如 myGenericFun
,您无法访问类型 T
因为它仅在编译时可用,但 erased在运行时。因此,如果你想在函数体中使用泛型类型作为普通类,你需要将类作为参数显式传递,如myGenericFun
所示。 .
如果您创建 inline
具有具体化的功能T
, T
的类型即使在运行时也可以访问,因此您不需要传递 Class<T>
此外。您可以使用 T
就好像这是一个普通的类(class) - 例如你可能想检查一个变量是否是一个实例 T
,然后您可以轻松完成:myVar is T
.
这样的inline
功能与 reified
类型 T
如下所示:
inline fun <reified T> myGenericFun()
如何reified
作品
您只能使用 reified
结合 inline
功能。通过这样做,您指示编译器将函数的字节码复制到调用函数的每个位置(编译器“内联”函数)。当您调用 inline
功能与 reified
类型,编译器必须能够知道作为类型参数传递的实际类型,以便它可以修改生成的字节码以直接使用相应的类。因此,像 myVar is T
这样的电话变成 myVar is String
在字节码中(如果类型参数是 String
)。
示例
让我们看一个例子来说明 reified
的帮助可。
我们要为 String
创建一个扩展函数调用toKotlinObject
尝试将 JSON 字符串转换为具有函数泛型类型 T
指定类型的普通 Kotlin 对象.我们可以使用 com.fasterxml.jackson.module.kotlin
为此,第一种方法如下:
a) 没有具体化类型的第一种方法
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
readValue
方法采用应该解析 JsonObject
的类型至。如果我们尝试获取 Class
类型参数T
,编译器提示:“不能使用 'T' 作为具体类型参数。请改用类。”
b) 使用显式 Class
的解决方法参数
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
作为一种解决方法,Class
的 T
可以作为方法参数,然后用作 readValue
的参数.这很有效,并且是通用 Java 代码中的常见模式。可以这样调用:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
c) Kotlin 方式:reified
使用 inline
功能与 reified
类型参数T
使得以不同方式实现功能成为可能:
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
无需使用Class
的 T
另外,T
可以像普通类一样使用。对于客户端,代码如下所示:
json.toKotlinObject<MyJsonType>()
重要提示:使用 Java
带有 reified
的内联函数type 不能从 Java 代码中调用。
关于generics - Kotlin 中的 reified 关键字是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45949584/