我在kotlin中使用安全转换选项,即as?
仍然在数据类型不兼容时收到类转换异常,当我通过编写用于执行大小写的通用方法来执行此操作时,会发生这种情况如果我直接执行转换,则返回的值将为安全转换所期望的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
}
castViaGenericMethod()->当数据不是TypeA类型时,此方法将引发ClassCastException。 castDirectly()->无法进行强制转换时,此方法返回null。
请建议如何完成。
答案 0 :(得分:2)
要解决您的问题,您可以使用reified
type:
inline fun <reified CONTEXT> castToContext() = data as? CONTEXT
之所以无法按预期工作的原因是,泛型在运行时被擦除了。
如果我们看一下字节码,就会发现在各处写有CONTEXT
通用类型的地方,它变成了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
因此,安全类型转换实际上会检查给定对象是否不是java/lang/Object
(1)类型,并在这种情况下将要返回的值设置为null
。但是由于它是java/lang/Object
类型的值,因此仅按原样返回该值。但是在调用方,字节码如下所示:
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL CastTest.castToContext ()Ljava/lang/Object; // the call
CHECKCAST TypeA // the type check
ARETURN
它在调用CHECKCAST TypeA
之后执行了另外的castToContext
,并且您得到了ClassCastException
,因为该值未为空(在运行时删除了通用类型信息)。