definicion java type-conversion method-overloading

java - jlabel definicion



¿Por qué java promueve el parámetro largo para flotar/duplicar cuando no hay un método que acepte largo? (4)

La razón por la que elige float sobre Long es que el autoboxing se agregó más tarde y por motivos de compatibilidad con versiones anteriores debería hacer la misma llamada que siempre.

Aquí hay un SSCCE que demuestra el comportamiento descrito (en mi humilde opinión):

public class Test { public static void print(int param) { System.out.println("int"); } public static void print(float param) { System.out.println("float"); } public static void print(Long param) { //<--Wrapper type System.out.println("Long"); } public static void main(String[] args) { long param = 100L; print(param); // output == float } }

¿Por qué java hace eso?


Tomasz Nurkiewicz señala la parte relevante de la especificación ( 15.12.2 en Java SE 7 JLS ), pero ¿por qué hacer eso? Para el código fuente de compatibilidad con versiones anteriores que apunta a 1.4 y anteriores, debe continuar llamando al mismo método sobrecargado. Por lo tanto, se deben ignorar las características de 1.5, y solo si el código no se compilaría de otra manera, se debería considerar el autoboxing.

En cuanto a por qué la conversión de long a float puede ser implícita, esa es solo una opción de diseño cuestionable.


Ver documentación

Capítulo 5. Conversiones y Promociones

5.1.2. Ampliación de conversión primitiva

19 conversiones específicas en tipos primitivos se llaman conversiones primitivas de ensanchamiento:

  • byte a corto, int, largo, flotante o doble
  • corto a int, largo, flotante o doble
  • char a int, long, float o double
  • int a long, float o double
  • largo para flotar o doble
  • flotar para duplicar

Por lo tanto, la conversión long para float es junto con las reglas.


La especificación del lenguaje Java es bastante clara en eso (el énfasis es mío):

15.12.2 Tiempo de compilación Paso 2: determinar la firma del método

[...]

  1. La primera fase (§15.12.2.2) realiza la resolución de sobrecarga sin permitir la conversión de boxeo o unboxing [...] Si no se encuentra un método aplicable durante esta fase, el procesamiento continúa hasta la segunda fase. [...]

  2. La segunda fase (§15.12.2.3) realiza la resolución de sobrecarga al tiempo que permite el boxeo y el desempaquetado [...]

  3. La tercera fase (§15.12.2.4) permite que la sobrecarga se combine con métodos de aridad variable, boxeo y desempaquetado.

Es decir, en el primer paso, solo print(int) e print(float) pueden ser apropiados. Este último coincide y no se realizan más investigaciones.

El motivo de tales reglas se explica en JLS también:

Esto garantiza que las llamadas que fueron válidas en el lenguaje de programación Java antes de Java SE 5.0 no se consideran ambiguas como el resultado de la introducción de métodos de aridad variable, boxeo implícito y / o unboxing.

Imagine que su clase de Test fue compilada contra Java 1.4 (antes de autoboxing). En ese caso, es claro: se debe elegir print(float) (suponiendo que estamos de acuerdo por qué el long de float se considera seguro y puede ser implícito ...) ya que print(Long) es completamente incompatible con el argumento long .

Más tarde compila el mismo código contra Java 5+. El compilador puede:

  • elija print(Long) como más " obvio " en este contexto. Por lo tanto, después de actualizar a Java 5, su programa se comporta de manera diferente ...

  • producir error de compilación ya que la llamada es ambigua. Por lo tanto, el código previamente correcto ya no se está compilando en Java 5 (que AFAIR nunca es el caso)

  • ... o preservar la semántica antigua y llamar al mismo método que en Java 1.4

Ahora debería comprender por qué se usa print(float) , porque se habría elegido en Java 1.4. Y Java tiene que ser compatible con versiones anteriores.