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