Kotlin 中的动态类型转换

12

我想使用KClass<Int>Any转换为Int,已经有一个KClass<Int>和一个实际上是IntAny

fun <T> cast(any: Any, clazz: KClass<*>): T = clazz.java.cast(any) 

cast(0, Int::class)

然而,我遇到了这个错误。

java.lang.ClassCastException: 无法将 java.lang.Integer 转换为 int

除了 any as Int,你知道其他解决方法吗?


1
你需要以某种方式使用 Kotlin 反射。Java 反射无法工作。 - voddan
2个回答

9

尝试将您的代码更改为:

fun <T: Any> cast(any: Any, clazz: KClass<out T>): T = clazz.javaObjectType.cast(any) 

解释

由于参数的类型为any,因此它始终是一个引用类型,基本类型将被封装。对于第二个参数,似乎Kotlin反射会优先选择基本类型而不是引用类型,这就是为什么Int::class.java默认为int而不是Integer的原因。通过使用javaObjectType,我们强制使用封装的引用类型。

替代方案

您还可以使用以下函数定义:

inline fun <reified T: Any> cast(any: Any): T = T::class.javaObjectType.cast(any) 

// usage

cast<Int>(0)

inline fun <reified T:Any> Any.cast() = this as? T 这是什么意思? - Hanzala

2
正如@voddan所指出的那样,Java反射在这里不起作用。这是因为从Java的角度来看,java.lang.Integerkotlin.Int之间没有关系。
Kirill Rakhman的答案对于非空类型非常有效。但是,如果T可为空,则无法使用T :: class。因此,我建议采取以下措施来处理可空类型(我不确定为什么问题说除了as之外的任何解决方案...)
inline fun <reified T> cast(any: Any?): T = any as T

使用方法

val l32: Number = cast(32L)
val ln1: Number? = cast(null) // works
val ln2: Number = cast(null) // fails at runtime

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接