Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

337
Views
¿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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!