Obtendo Exceção quando Safe-Fundição de tipo genérico em Kotlin

Vivek Gupta:

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.

Roland:

Para corrigir o problema, você poderia usar um reifiedtipo :

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 CONTEXTtipo -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 TypeAdepois de chamar castToContexte lá você obter o seu ClassCastExceptioncomo o valor não foi anulado (informações de tipo genérico foi apagado em tempo de execução).

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=212039&siteId=1
Recomendado
Clasificación