Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

334
Visualizações
¿Por qué es posible una conversión de Double a <T : Number>, pero no de Double a Int?

A continuación, tengo una función genérica fun <T : Number> sum(list : List<T>) : T con un parámetro de tipo T : Number .

En la función, resumo los números de la lista como una sum : Double y lanza la suma al final con la return sum as T

Por ejemplo, si se pasa una lista de Int , también obtengo un Int , y esto funciona.

 fun <T : Number> sum(list : List<T>) : T { var sum = 0.0 for(x in list) sum += x.toDouble() return sum as T } fun main() { println(sum(listOf(1,2,3))) } // prints 6

Sin embargo, lo siguiente no funciona, y me pregunto por qué las funciones genéricas anteriores funcionan, pero la conversión directa de un Double a un Int no lo hace.

 fun main() { val d : Double = 6.0 val i = d as Int // java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer println(i) }

Debo admitir que esperaba que ambos casos fallaran, pero sorprendentemente, la función genérica funciona y no sé por qué.

Entonces, la pregunta es: ¿Por qué funciona la función genérica y no arroja una ClassCastException cuando se convierte de Double a Int?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Tenga en cuenta que en el primer fragmento de código, que "funciona", en realidad no está enviando el resultado a Int . Si está utilizando IntelliJ, debería haber marcado el reparto como un "reparto sin marcar". Esto significa que en tiempo de ejecución, no se comprueba si la sum se puede convertir realmente al tipo T Solo comprueba que sum es un Number , y listo. No se realiza nada más.

Puede ver que el valor devuelto sigue siendo un Double , no un Int al imprimir:

 println(sum(listOf<Int>(1,2,3)) is Int) // false println(sum(listOf<Int>(1,2,3)) is Double) // true

Y como explican otras respuestas, esto se debe al borrado de tipos.

La razón por la que aún ve 6 , pero no 6.0 es un poco más complicada. El compilador de Kotlin ve que la llamada sum aquí debería devolver un Int (en este punto, los tipos aún no se han borrado), por lo que encuentra la sobrecarga de println que toma un Int , que se alinea con el Java System.out.prinln(int) método. Para llamar a este método, el compilador debe generar un código que convierta el Number borrado por tipo que devuelve la sum en un int , por lo que llama a Number.intValue .

Por lo tanto, esto es lo que se genera:

 33: invokestatic #69 // Method sum:(Ljava/util/List;)Ljava/lang/Number; 36: invokevirtual #73 // Method java/lang/Number.intValue:()I 39: invokevirtual #79 // Method java/io/PrintStream.println:(I)V

Si hubiera obligado al compilador a llamar a pritnln(Any) , imprimiría 6.0 :

 val any: Any = sum(listOf<Int>(1,2,3)) println(any)
over 4 years ago · Santiago Trujillo Relatório

0

Esto se debe a que el tipo de borrado . En su caso, la información genérica solo está disponible durante la compilación. En tiempo de ejecución, la sum as T hace notar, porque no está claro qué es T. Por ejemplo, no es posible imprimir el tipo de T. Es un molde no verificado. También podría cambiar el tipo T de Number a String , lo que no tiene sentido, pero compilaría. Por lo tanto, la función no lanzará ClassCastException porque en realidad no emite. Si cambia la función de sum a un tipo refinado , que conserva la información de tipo en tiempo de ejecución, hará la conversión y arrojará el error:

 inline fun <reified T : Number> sum(list: List<T>): T { var sum = 0.0 for (x in list) sum += x.toDouble() return sum as T // java.lang.ClassCastException }
over 4 years ago · Santiago Trujillo Relatório

0

Hace el lanzamiento, pero el lanzamiento está en el límite superior de su tipo genérico, que es Number

Puede ver que esto sucede en la versión descompilada de su código:

 public static final Number sum(@NotNull List list) { Intrinsics.checkNotNullParameter(list, "list"); double sum = 0.0D; Number x; for(Iterator var4 = list.iterator(); var4.hasNext(); sum += x.doubleValue()) { x = (Number)var4.next(); } return (Number)sum; }

Si observa ese código, el compilador también le dirá que la conversión a T es redundante, porque esto ya está garantizado.

El equivalente sería:

 fun main() { val d : Double = 6.0 val i = d as Number println(i) }

Lo que tampoco causa la excepción ClassCast.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda