generic java boxing autoboxing

generic java



¿El autoboxing llama a valueOf()? (4)

El tutorial de autoboxing de Oracle indica de manera práctica que li.add (i) está compilado para li.add (Integer.valueOf (i)), donde i es un int. Pero no sé si el tutorial debería considerarse una fuente autorizada.

Estoy ejecutando Oracle Java 1.7.0_72, parece que usa valueOf. A continuación se muestra un código y el bytecode para él. El bytecode muestra que está usando valueOf.

public class AutoBoxing { /** * @param args the command line arguments */ public static void main(String[] args) { Integer x = 5; int i = x; System.out.println(x.toString()); } } Compiled from "AutoBoxing.java" public class testing.AutoBoxing { public testing.AutoBoxing(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_5 1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 4: astore_1 5: aload_1 6: invokevirtual #3 // Method java/lang/Integer.intValue:()I 9: istore_2 10: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 13: aload_1 14: invokevirtual #5 // Method java/lang/Integer.toString:()Ljava/lang/String; 17: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 20: return

Pero no sé qué usa Open JDK. Lo probaré.

Estoy tratando de determinar si se garantiza que las siguientes afirmaciones son verdaderas:

((Boolean)true) == Boolean.TRUE ((Boolean)true) == Boolean.valueOf(true) ((Integer)1) == Integer.valueOf(1)

Siempre he supuesto que el autoboxing fue equivalente a llamar a valueOf() en el tipo correspondiente. Cada discussion que he visto sobre el topic parece support mi suposición. Pero todo lo que pude encontrar en el JLS fue el siguiente ( §5.1.7 ):

Si el valor p se encasilla es un literal entero de tipo int entre -128 y 127 inclusive (§3.10.1), o el literal booleano true o false (§3.10.3), o un literal de carácter entre ''/u0000'' y ''/u007f'' inclusive (§3.10.4), entonces b son los resultados de dos conversiones de boxeo cualquiera de p . Siempre es el caso que a == b .

Eso describe un comportamiento idéntico similar al de valueOf() . Pero no parece haber ninguna garantía de que valueOf() se invoque realmente, lo que significa que podría haber una implementación teórica que mantenga un caché dedicado y separado para los valores de autoboxed. En tal caso, puede que no exista igualdad de identidad entre los valores almacenados en la memoria caché en caché y los valores normales en la caché.

El tutorial de autoboxing de Oracle indica de manera práctica que li.add(i) está compilado para li.add(Integer.valueOf(i)) , donde i es un int . Pero no sé si el tutorial debería considerarse una fuente autorizada.

* Es una garantía ligeramente más débil que valueOf() , ya que solo se refiere a valores literales.


Autoboxing se implementa completamente utilizando valueOf() ... en OpenJDK. Si esa es su implementación, siga leyendo ... si no, salte a continuación.

((Boolean)true) == Boolean.TRUE ((Boolean)true) == Boolean.valueOf(true)

La documentación de Java indica que Boolean.valueOf() siempre devuelve Boolean.TRUE o Boolean.FALSE , por lo tanto, las comparaciones de referencia en estos casos tendrán éxito.

((Integer)1) == Integer.valueOf(1)

Para este ejemplo en particular, bajo la implementación OpenJDK con configuraciones predeterminadas, probablemente funcionará en virtud del hecho de que seleccionó un valor <128 que se almacena en caché al inicio (aunque esto puede ser anulado como una línea de comando arg). También puede funcionar para valores más grandes si se utiliza con frecuencia suficiente para ser almacenado en caché. A menos que esté trabajando bajo supuestos "seguros" sobre el caché Integer, no espere que la comparación de referencia sea una igualdad.

Long , Short , Character y Byte implementan incidentalmente este almacenamiento en caché también, pero a diferencia de Integer , no se puede sintonizar. Byte siempre funcionará si está comparando referencias de autobox / valueOf() ya que, obviamente, no puede salir del rango. Float y Double , como era de esperar, siempre crearán una nueva instancia.

Ahora, en términos puramente genéricos? Consulte esta sección de JLS : DEBE recibir referencias iguales para boolean y cualquier int o char dentro del rango de -128 a 127. No hay garantías para nada más.


Hasta que la especificación del lenguaje lo mencione, no se garantiza que el autoboxing sea equivalente a una llamada a los métodos valueOf estáticos. Es un aspecto de implementación , no parte de la especificación de conversión de boxeo. Una implementación es teóricamente libre de usar otro mecanismo siempre que cumpla con la regla que mencionó desde el JLS.

En la práctica, hay muchos informes de errores Sun JDK (por ejemplo, JDK-4990346 y JDK-6628737 ) que implican claramente que cuando se introdujo el autoboxing en Java 5, la intención era hacer que el compilador confiara en valueOf como se indica en JDK-6628737 :

Los métodos de fábrica estáticos Integer.valueOf (int), Long.valueOf (long), etc. se introdujeron en JDK 5 para que javac implemente el comportamiento de almacenamiento en caché requerido por la especificación de autoboxing.

Pero eso es solo para javac, no necesariamente para todos los compiladores.


Primero pensé que tu pregunta era una trampa de topic

Sin embargo, después de su comentario sobre @ElliottFrisch, me di cuenta de que era diferente:

Sé que el compilador se comporta de esa manera. Estoy tratando de averiguar si ese comportamiento está garantizado.

Para otros lectores, supongamos que "se comporta de esa manera" significa usar valueOf .

Recuerde que hay compiladores múltiples para Java. Para ser "legales" deben seguir el contrato dado en el JLS . Por lo tanto, siempre que se respeten todas las reglas aquí, no hay garantía de cómo se implementa internamente el autoboxing.

Pero no veo ninguna razón para no usar valueOf , especialmente que usa los valores en caché y es la forma recomendada según este artículo de Joseph D. Darcy.