Estoy usando la opción de fundición seguro en Kotlin es decir, as?
todavía estoy recibiendo excepción de difusión clase cuando los tipos de datos no son compatibles, esto sucede cuando estoy haciendo esto a través de un método genérico por escrito para llevar a cabo caso, sin embargo si realizo directamente el elenco Devuelve nula como se espera de un 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 lanza ClassCastException cuando no es el tipo de datos TypeA. castDirectly () -> esto devuelve null cuando el elenco no es posible.
Para sugerir cómo se puede hacer esto.
Para solucionar el problema se podría utilizar un reified
tipo :
inline fun <reified CONTEXT> castToContext() = data as? CONTEXT
La razón, ¿por qué no funcionó como se esperaba, es decir, que los tipos genéricos se borran en tiempo de ejecución.
Si nos fijamos en el código de bytes, vemos que en todas partes, donde su CONTEXT
tipo -generic está escrito, se convierte en 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
Por lo que el elenco segura realmente hace una comprobación de si el objeto dado no es del tipo java/lang/Object
(1) y establece el valor a ser devuelto a null
si ese es el caso. Pero como es de tipo java/lang/Object
, el valor se acaba de regresar como está. En el lado llamando sin embargo las miradas de código de bytes de la siguiente manera:
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL CastTest.castToContext ()Ljava/lang/Object; // the call
CHECKCAST TypeA // the type check
ARETURN
Se hace un adicional CHECKCAST TypeA
después de llamar castToContext
y hay que obtener su ClassCastException
como el valor no fue anulado (información de tipo genérico se borró en tiempo de ejecución).