我在kotlin中使用安全转换选项,即< code>as?当数据类型不兼容时,我仍然会遇到类转换异常,这是在我通过为执行case而编写的泛型方法执行此操作时发生的,但是,如果我直接执行转换,它会像安全转换所预期的那样返回null
class CastTest(val data: Any) {
fun castViaGenericMethod(): TypeA? {
return castToContext<TypeA>()
}
fun castDirectly(): TypeA? {
return data as? TypeA
}
private fun <CONTEXT> castToContext(): CONTEXT? = data as? CONTEXT
}
< code > castViaGenericMethod()-
请建议如何做到这一点。
要解决您的问题,您可以使用< code >具体化类型:
inline fun <reified CONTEXT> castToContext() = data as? CONTEXT
为什么它没有像你预期的那样工作的原因是,泛型类型在运行时被删除了。
如果我们看一下字节码,我们会发现无论你的 CONTEXT-generic
类型写在哪里,它都变成了 java/lang/Object
:
private final castToContext()Ljava/lang/Object;
L0
LINENUMBER 12 L0
ALOAD 0
GETFIELD CastTest.data : Ljava/lang/Object;
DUP
INSTANCEOF java/lang/Object // (1)
IFNE L1 // (1)
POP // (2)
ACONST_NULL // (2)
L1
ARETURN
L2
LOCALVARIABLE this LCastTest; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
因此,安全强制转换实际上会检查给定的对象是否不是< code>java/lang/Object (1)类型,如果是这种情况,则将值设置为< code>null。但是由于它的类型是< code>java/lang/Object,所以值只是按原样返回。然而,在调用方,字节代码看起来如下:
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL CastTest.castToContext ()Ljava/lang/Object; // the call
CHECKCAST TypeA // the type check
ARETURN
它在调用castToContext
后执行额外的CHECKCAST TypeA
,然后您会得到您的ClassCastExc的
,因为值没有无效(泛型类型信息在运行时被擦除)。