我正在尝试了解reified
关键字的目的,显然它使我们能够对泛型进行反思。
但是,当我忽略它时,它也可以正常工作。任何人都想解释一下这何时会产生实际变化?
reified
好处fun <T> myGenericFun(c: Class<T>)
在这类通用函数的主体中myGenericFun
,您无法访问该类型,T
因为它仅在编译时可用,而在运行时被擦除。因此,如果要将泛型用作函数主体中的普通类,则需要显式传递该类作为参数,如中所示myGenericFun
。
如果您创建inline
带有reified 的函数,即使在运行时也可以访问T
的类型T
,因此您无需Class<T>
额外传递。您可以一起工作T
,就好像它是一个正常的类-例如,你可能要检查一个变量是否是一个实例 T
,您可以轻松做到,那么:myVar is T
。
inline
具有reified
类型的此类函数T
如下所示:
inline fun <reified T> myGenericFun()
reified
工作您只能reified
与inline
功能结合使用。这样的函数使编译器将函数的字节码复制到使用该函数的每个位置(该函数被“内联”)。当您调用带有类型化的内联函数时,编译器知道用作类型实参的实际类型,并修改生成的字节码以直接使用相应的类。因此,在字节码中和在运行时,调用如myVar is T
成为myVar is String
(如果type参数为String
)成为。
让我们看一个示例,该示例显示了如何帮助reified
您。我们要创建一个扩展功能String
叫toKotlinObject
,试图JSON字符串转换为纯科特林对象与函数的泛型类型指定的类型T
。我们可以使用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
type参数的T
,则编译器会抱怨:“不能将'T'用作化类型参数。请改用类。”
b)使用显式Class
参数的解决方法
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
解决方法是Class
,T
可以将of作为方法参数,然后将其用作参数readValue
。这是可行的,并且是通用Java代码中的常见模式。可以这样称呼:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
c)科特林方式: reified
使用inline
带有reified
类型参数T
的函数可以以不同的方式实现该函数:
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
无需另外使用Class
of T
,T
可以像普通类一样使用。对于客户端,代码如下所示:
json.toKotlinObject<MyJsonType>()
reified
类型的内联函数不能从Java代码中调用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句