Kotlin中的关键字关键字是如何工作的?

我试图理解关键字关键字的目的,显然它允许我们对generics进行思考 。

但是,当我离开它时,它工作得很好。 任何人都在意解释什么时候会产生实际的差异

为什么我们需要它

在一个普通的通用函数fun myGenericFun(c:Class)中,不能访问Ttypes,因为它只在编译时可用,但在运行时擦除 。 因此,如果你想使用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参数Tinline函数可以实现我们的function,如下所示:

 inline fun  String.toKotlinObject(): T { val mapper = jacksonObjectMapper() return mapper.readValue(JsonObject(this).encode(), T::class.java) } 

T不需要另外通过T ClassT可以像普通类一样使用。 对于客户端代码如下所示:

 "{}".toKotlinObject() 

使用Java:重要注意事项

带有特定types的内联函数不能从Java代码中调用