Eu estou usando a opção de elenco seguro em Kotlin ou seja, as?
ainda estou recebendo exceção de lançamento de classe quando os tipos de dados não são compatíveis, isto está acontecendo quando eu estou fazendo isso por meio de um método genérico escrito para executar caso, no entanto, se eu executar diretamente o elenco retorna null como esperado de um elenco segura
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 () -> este método lança ClassCastException quando não é tipo de dados TypeA. castDirectly () -> este retorna nulo quando o elenco não é possível.
Por favor, sugerem como isso pode ser feito.
Para corrigir o problema, você poderia usar um reified
tipo :
inline fun <reified CONTEXT> castToContext() = data as? CONTEXT
A razão, por que não funcionou como você espera, é que tipos genéricos são apagados durante a execução.
Se olharmos para o código de byte, vemos que em todos os lugares, onde o seu CONTEXT
tipo -generic está escrito, torna-se 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
Então, o elenco segura realmente faz uma verificação se o objeto fornecido não é do tipo java/lang/Object
(1) e define o valor a ser devolvido para null
, se for o caso. Mas como ele é do tipo java/lang/Object
, o valor é devolvido como é. No lado chamando no entanto os olhares de código byte da seguinte forma:
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL CastTest.castToContext ()Ljava/lang/Object; // the call
CHECKCAST TypeA // the type check
ARETURN
Ele faz um adicional CHECKCAST TypeA
depois de chamar castToContext
e lá você obter o seu ClassCastException
como o valor não foi anulado (informações de tipo genérico foi apagado em tempo de execução).