Kotlin中的关键字关键词究竟是干什么的?
我试图理解关键字关键字的目的,显然它允许我们对泛型进行思考 。
但是,当我离开它时,它工作得很好。 任何人都在意解释什么时候会产生实际的差异?
为什么我们需要它
在一个普通的通用函数fun <T> myGenericFun(c:Class<T>)
中,不能访问T
类型,因为它只在编译时可用,但在运行时擦除 。 因此,如果你想使用泛型类型作为函数体中的普通类,你需要显式地传递类作为参数,就像我的例子。
如果你使用一个具体化的T
做了一个inline
函数,那么即使在运行时也可以访问T
的类型,因此你不需要另外传递Class<T>
。 你可以像使用普通的类一样使用T
,比如你可能想要检查一个变量是否是T
一个实例 ,你可以很容易的做到: myVar is T
这样的功能如下所示:
inline fun <reified T> myGenericFun()
胡德如何运作
你只能使用与inline
函数结合使用。 这样的函数使编译器将函数的字节码复制到函数正在被使用的每个地方(函数被“内联”)。 当您使用具体化类型调用内联函数时, 编译器知道用作类型参数的实际类型,并修改生成的字节码以直接使用相应的类。 因此,像myVar is T
这样的调用myVar is T
成为myVar is String
,如果类型参数是String
,在字节码和运行时。
例
让我们来看一个例子,其中reified
是真正有用的。 我们要为String
创建一个名为toKotlinObject
的扩展函数,它试图将JSON字符串转换为由函数类型T
指定的Kotlin对象。 我们可以使用com.fasterxml.jackson.module.kotlin
来解决这个问题,第一种方法如下:
编译错误
fun <T> String.toKotlinObject(): T { val mapper = jacksonObjectMapper() //does not compile! return mapper.readValue(JsonObject(this).encode(), T::class.java) }
readValue
方法要我们告诉哪个类型应该解析JsonObject
。 我们尝试使用类型参数T
并获得它的Class
。
这不起作用,编译器告诉我们: “不能使用'T'作为实体类型参数,而是使用类。”
没有通过的工作示例
fun <T> String.toKotlinObject(c: Class<T>): T { val mapper = jacksonObjectMapper() return mapper.readValue(JsonObject(this).encode(), c) }
下一步是将显式的T
类直接作为参数传递给readValue
。 这是有效的,这是我们在Java中所做的。 它可以这样调用:
"{}".toKotlinObject(MyJsonType::class.java)
具体化了
使用带有特定类型参数T
的inline
函数可以实现我们的功能,如下所示:
inline fun <reified T> String.toKotlinObject(): T { val mapper = jacksonObjectMapper() return mapper.readValue(JsonObject(this).encode(), T::class.java) }
T
不需要另外通过T
Class
, T
可以像普通类一样使用。 对于客户端代码如下所示:
"{}".toKotlinObject<MyJsonType>()
重要
内联指定函数不能从Java代码中调用 。