Explicación detallada del embalaje y unboxing de Java
Prefacio:
Para comprender los conceptos de embalaje y unboxing, debe comprender los tipos de datos de Java
Cuadro: Tipos básicos de paquete con sus tipos de referencia correspondientes para hacer que tengan las propiedades de los objetos. Int empaquetado en entero, flotante empaquetado en flotador
Unboxing: en contraste con el boxeo, simplifica los objetos de tipos de referencia a los datos de los tipos de valor
Entero a = 100; Este es un boxeo automático (el compilador llama valor entero estático (int i)) int b = nuevo entero (100); Este es un boxeo automático
Ver el siguiente código
M1
Public Class DataType {public static void main (string args []) {dataType dt = new DataType (); dt.m11 (); dt.m12 (); } public void m11 () {Integer a = nuevo entero (100); Entero b = 100; System.out.println ("resultado m11" + (a == b)); } public void m12 () {Integer a = nuevo entero (128); Entero b = 128; System.out.println ("resultado M12" + (a == b)); }}¿Cuáles son los resultados de la impresión?
M11 Resultado Falso M12 Resultado Falso
"==" compara la dirección, mientras que las direcciones de los objetos A y B son diferentes, es decir, son dos objetos, por lo que ambos son falsos
Analización de Bytecode a través de Javap, el contenido es el siguiente
público vacío m11 (); Código: 0: nuevo #44; // clase java/lang/entero 3: dup 4: bipush 100 6: invokespecial #46; // método java/lang/integer. "<Init>" :( i) v 9: store_1 10: bipush 100 12: invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 15: Store_2 16: Getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 19: nuevo #59; // clase java/lang/stringBuilder 22: dup 23: ldc #61; // String M11 Resultado 25: Invokespecial #63; // método java/lang/stringBuilder. "<Init>" :( ljava/lang/string;) v 28: Aload_1 29: Aload_2 30: IF_ACMPNE 37 33: ICONST_1 34: GOTO 38 38: ICONST_0 38: InvokeVirtual #66; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 41: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 44: InvokeVirtual #74; // método java/io/printstream.println: (ljava/lang/string;) v 47: return public void m12 (); Código: 0: nuevo #74; // clase java/lang/entero 3: dup 4: sipush 128 7: invokespecial #46; // método java/lang/integer. "<Init>" :( i) v 10: store_1 11: sipush 128 14: invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 17: Store_2 18: Getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 21: nuevo #59; // clase java/lang/stringBuilder 24: dup 25: ldc #82; // Cadena M12 Resultado 27: Invokespecial #63; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 43: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/stringBuilder; 46: InvokeVirtual #74; // Método java/io/printstream.println: (ljava/lang/string;) v 49: return </itil> </init> </init> </init>
m2
Public Class DataType {public static void main (string args []) {dataType dt = new DataType (); dt.m21 (); dt.m22 (); } public void m21 () {Integer a = nuevo entero (100); Entero b = nuevo entero (100); System.out.println ("resultado m21" + (a == b)); } public void m22 () {Integer a = nuevo entero (128); Entero b = nuevo entero (128); System.out.println ("resultado m22" + (a == b)); }}El resultado de la impresión es
Resultado m21 FALSEM22 Resultado Falso
A y B siguen siendo dos objetos
Contenido de análisis de Javap
público vacío m21 (); Código: 0: nuevo #44; // clase java/lang/entero 3: dup 4: bipush 100 6: invokespecial #46; // método java/lang/integer. "<Init>" :( i) v 9: store_1 10: nuevo #44; // clase java/lang/entero 13: dup 14: bipush 100 16: invokespecial #46; // método java/lang/integer. "<Init>" :( i) v 19: store_2 20: getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 23: nuevo #59; // clase java/lang/stringBuilder 26: dup 27: ldc #84; // Cadena M21 Resultado 29: Invokespecial #63; // Método java/lang/stringBuilder. "<Init>" :( ljava/lang/string;) v 32: Aload_1 33: Aload_2 34: IF_ACMPNE 41 37: ICONST_1 38: GOTO 42 41: ICONST_0 42: InvokeVirtual #66; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 45: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 48: InvokeVirtual #74; // método java/io/printstream.println: (ljava/lang/string;) v 51: returnPublic void m22 (); Código: 0: nuevo #74; // clase java/lang/entero 3: dup 4: sipush 128 7: invokespecial #46; // método java/lang/integer. "<Init>" :( i) v 10: store_1 11: nuevo #44; // clase java/lang/entero 14: dup 15: sipush 128 18: invokespecial #46; // método java/lang/integer. "<Init>" :( i) v 21: store_2 22: getStatic #53; // Field java/lang/system.out: ljava/io/printstream; 25: nuevo #59; // clase java/lang/stringBuilder 28: dup 29: ldc #86; // Cadena M22 Resultado 31: Invokespecial #63; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 47: InvokeVirtual #70; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 47: InvokeVirtual #70; // método java/lang/stringBuilder; 40: InvokeVirtual #70; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 47: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 50: InvokeVirtual #74; // método java/io/printstream.println: (ljava/lang/string;) v 53: return
m3
Public Class DataType {public static void main (string args []) {dataType dt = new DataType (); dt.m31 (); dt.m32 (); } public void m31 () {Integer a = 100; Entero b = 100; System.out.println ("resultado M31" + (a == b)); } public void m32 () {Integer a = 128; Entero b = 128; System.out.println ("resultado m32" + (a == b)); }}Resultados de impresión
resultado m31 TRUEM32 Resultado Falso
¿Por qué hay una primera verdadera y una segunda falsa? Observe los datos analizados por Javap
Contenido de análisis de Javap
público vacío M31 (); Código: 0: Bipush 100 2: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 5: Store_1 6: Bipush 100 8: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 11: Store_2 12: Getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 15: nuevo #59; // clase java/lang/stringBuilder 18: dup 19: ldc #88; // String M31 Resultado 21: Invokespecial #63; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 37: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 40: InvokeVirtual #74; // método java/io/printstream.println: (ljava/lang/string;) v 43: returnPublic void m32 (); Código: 0: Sipush 128 3: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 6: Astore_1 7: Sipush 128 10: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 13: Store_2 14: Getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 17: nuevo #59; // clase java/lang/stringBuilder 20: DUP 21: LDC #90; // Cadena M32 Resultado 23: Invokespecial #63; // método java/lang/stringBuilder. "<Init>" :( ljava/lang/string;) v 26: Aload_1 27: Aload_2 28: IF_ACMPNE 35 31: IconSt_1 32: goto 36 35: iconst_0 36: InvokeVirtual #66; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 39: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 42: InvokeVirtual #74; // método java/io/printString.println: (ljava/lang/string;) v 45: return
m4
Public Class DataType {public static void main (string args []) {dataType dt = new DataType (); dt.m41 (); dt.m42 (); } public void m41 () {integer a = integer.valueOf (100); Entero b = 100; System.out.println ("resultado M41" + (a == b)); } public void m42 () {integer a = integer.valueOf (128); Entero b = 128; System.out.println ("resultado M42" + (a == b)); }}Resultados de impresión
Resultado M41 TRUEM42 Resultado Falso
Contenido de análisis de Javap
público vacío M41 (); Código: 0: Bipush 100 2: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 5: Store_1 6: Bipush 100 8: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 11: Store_2 12: Getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 15: nuevo #59; // clase java/lang/stringBuilder 18: dup 19: ldc #92; // String M41 Resultado 21: Invokespecial #63; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 37: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 40: InvokeVirtual #74; // método java/io/printstream.println: (ljava/lang/string;) v 43: returnPublic void m42 (); Código: 0: Sipush 128 3: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 6: Astore_1 7: Sipush 128 10: Invokestatic #49; // método java/lang/integer.valueof: (i) ljava/lang/integer; 13: Store_2 14: Getstatic #53; // Field java/lang/system.out: ljava/io/printstream; 17: nuevo #59; // clase java/lang/stringBuilder 20: DUP 21: LDC #94; // Cadena M42 Resultado 23: Invokespecial #63; // método java/lang/stringBuilder. "<Init>" :( ljava/lang/string;) v 26: Aload_1 27: Aload_2 28: IF_ACMPNE 35 31: IconSt_1 32: goto 36 35: iconst_0 36: InvokeVirtual #66; // método java/lang/stringBuilder.append: (z) ljava/lang/stringBuilder; 39: InvokeVirtual #70; // método java/lang/stringBuilder.ToString :() ljava/lang/string; 42: InvokeVirtual #74; // método java/io/printstream.println: (ljava/lang/string;) v 45: return}
analizar
Javap es una herramienta que viene con Java. El compilador Java (el código anterior solo usa el tipo de datos Javap -C). Es una buena herramienta para analizar el código. Para más detalles, por favor, busque en Google.
Echemos un vistazo a M4 primero. ¿Por qué aparece "verdadero" en el resultado de la ejecución? Verdadero significa que A y B son el mismo objeto.
Pero el objeto A se genera llamando a Integer.ValueOf (), y B es un objeto generado por el boxeo automático. ¿Por qué es el mismo objeto? Echemos un vistazo al Bytecode nuevamente. Después de todo, los programas Java dependen de máquinas virtuales para ejecutar bytecode.
El método M41 solo aplica valuef () una vez, pero aparece dos veces en el bytecode, lo que significa que ValueOf () también se llama durante el boxeo automático.
La siguiente es la implementación específica de valueOf ()
/** * Devuelve una instancia <tt> entero </tt> que representa el valor especificado * <tt> int </tt>. * Si no se requiere una nueva instancia <tt> Integer </tt>, este método * generalmente debe usarse en preferencia al constructor * {@link #Integer (int)}, ya que es probable que este método produzca * rendimiento de tiempo significativamente mejor al almacenarse en caché * los valores solicitados frecuentemente. * * @param i an <code> int </code> valor. * @return a <tt> entero </tt> instancia que representa <tt> i </tt>. * @since 1.5 */public static entero Valueof (int i) {final int offset = 128; if (i> = -128 && i <= 127) {// debe almacenar en caché devolver integercache.cache [i + offset];} return nuevo (i);}En los números entre [-128, 127], el valor de devuelve un objeto en el caché, por lo que las dos llamadas devuelven el mismo objeto.
Gracias por leer, espero que pueda ayudarte. ¡Gracias por su apoyo para este sitio!