generic java primitive autoboxing

generic java



¿Esto realmente se está ampliando contra el autoboxing? (3)

En el primer caso, tiene lugar una conversión de ampliación. Esto se puede ver al ejecutar el programa de utilidad "javap" (incluido con el JDK), en la clase compilada:

public static void main(java.lang.String[]); Code: 0: iconst_ 5 1: istore_ 1 2: iload_ 1 3: i2l 4: invokestatic #6; //Method hello:(J)V 7: return }

Claramente, usted ve el I2L, que es el mnemónico para la instrucción de código de bytes Integer-To-Long ensanchado. Ver referencia aquí .

Y en el otro caso, reemplazando la "x larga" con la firma del objeto "Long x", tendrá este código en el método principal:

public static void main(java.lang.String[]); Code: 0: iconst_ 5 1: istore_ 1 2: iload_ 1 3: invokestatic #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 6: invokestatic #7; //Method hello:(Ljava/lang/Integer;)V 9: return }

Entonces ves que el compilador ha creado la instrucción Integer.valueOf (int), para encapsular la primitiva dentro del envoltorio.

Vi esto en una respuesta a otra pregunta , en referencia a las deficiencias de la especificación Java:

Hay más deficiencias y este es un tema sutil. Mira esto :

public class methodOverloading{ public static void hello(Integer x){ System.out.println("Integer"); } public static void hello(long x){ System.out.println("long"); } public static void main(String[] args){ int i = 5; hello(i); } }

Aquí se imprimirá "largo" (no lo he comprobado), porque el compilador elige> ensanchar sobre autoboxing. ¡Tenga cuidado al usar el autoboxing o no lo use en absoluto!

¿Estamos seguros de que esto es en realidad un ejemplo de ampliación en lugar de autoboxing, o es algo totalmente diferente?

En mi exploración inicial, estaría de acuerdo con la afirmación de que la salida sería "larga" sobre la base de que i declararon como una primitiva y no como un objeto. Sin embargo, si cambiaste

hello(long x)

a

hello(Long x)

la salida imprimiría "Integer"

¿Qué está pasando realmente aquí? No sé nada sobre los compiladores / intérpretes de bytecode para java ...


Otra cosa interesante con este ejemplo es la sobrecarga de métodos. La combinación de ampliación de tipos y sobrecarga de métodos solo funciona porque el compilador tiene que tomar una decisión sobre qué método elegir. Considere el siguiente ejemplo:

public static void hello(Collection x){ System.out.println("Collection"); } public static void hello(List x){ System.out.println("List"); } public static void main(String[] args){ Collection col = new ArrayList(); hello(col); }

No utiliza el tipo de tiempo de ejecución que es Lista, utiliza el tipo de tiempo de compilación que es Colección y, por lo tanto, imprime "Colección".

Te animo a que leas Effective Java , que me abrió los ojos a algunos casos de esquina de JLS.


Sí lo es, pruébalo en una prueba. Verá impreso "largo". Se está ampliando porque Java elegirá ampliar el int en mucho antes de que elija autoboxearlo en un Entero, por lo que se elige el método de saludo (largo).

Editar: la publicación original a la que se hace referencia .

Editar más: La razón por la que la segunda opción imprimirá Entero es porque no hay una "ampliación" en una primitiva más grande como una opción, por lo que DEBE empaquetarla, por lo tanto, el Entero es la única opción. Además, java solo se autoboxeará al tipo original, por lo que daría un error de compilación si deja el saludo (Largo) y el saludo eliminado (Entero).