我试图了解reified
关键字的目的,显然它使我们能够对泛型进行反思。
但是,当我忽略它时,它也可以正常工作。有人在乎解释时,这使得实际的区别?
我试图了解reified
关键字的目的,显然它使我们能够对泛型进行反思。
但是,当我忽略它时,它也可以正常工作。有人在乎解释时,这使得实际的区别?
Answers:
reified
好处fun <T> myGenericFun(c: Class<T>)
在这类通用函数的主体中myGenericFun
,您无法访问该类型,T
因为它仅在编译时可用,而在运行时被擦除。因此,如果要将泛型类型用作函数体中的普通类,则需要显式传递该类作为参数,如中所示myGenericFun
。
但是,如果inline
使用带修饰符 的函数创建函数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
可以将的设为方法参数,然后将其用作的参数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代码中调用。
简单
*已修正是在编译时授予使用权限(在函数内部访问T)
例如:
inline fun <reified T:Any> String.convertToObject(): T{
val gson = Gson()
return gson.fromJson(this,T::class.java)
}
使用像:
val jsonStringResponse = "{"name":"bruno" , "age":"14" , "world":"mars"}"
val userObject = jsonStringResponse.convertToObject<User>()
println(user.name)