Detailed explanation of Java packing and unboxing
Preface:
To understand the concepts of packing and unboxing, you must understand Java data types
Box: Package basic types with their corresponding reference types to make them have the properties of objects. Int packaged into Integer, float packaged into Float
Unboxing: In contrast to boxing, simplifies objects of reference types to data of value types
Integer a = 100; This is automatic boxing (the compiler calls static Integer valueOf(int i)) int b = new Integer(100); This is automatic boxing
See the following code
m1
public class DataType { public static void main(String args[]) { DataType dt = new DataType(); dt.m11(); dt.m12(); } public void m11() { Integer a = new Integer(100); Integer b = 100; System.out.println("m11 result " + (a == b)); } public void m12() { Integer a = new Integer(128); Integer b = 128; System.out.println("m12 result " + (a == b)); } }What are the print results?
m11 result false m12 result false
"==" compares the address, while the addresses of objects a and b are different, that is, they are two objects, so they are both false
Parsing bytecode through Javap, the content is as follows
public void m11(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: bipush 100 6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 9: store_1 10: bipush 100 12: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 15: store_2 16: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 19: new #59; //class java/lang/StringBuilder 22: dup 23: ldc #61; //String m11 result 25: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 28: aload_1 29: aload_2 30: if_acmpne 37 33: iconst_1 34: goto 38 37: iconst_0 38: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 41: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 44: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 47: return public void m12(); Code: 0: new #74; //class java/lang/Integer 3: dup 4: sipush 128 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 10: store_1 11: sipush 128 14: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 17: store_2 18: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 21: new #59; //class java/lang/StringBuilder 24: dup 25: ldc #82; //String m12 result 27: invokespecial #63; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 43: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/StringBuilder; 46: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 49: return</init></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 = new Integer(100); Integer b = new Integer(100); System.out.println("m21 result " + (a == b)); } public void m22() { Integer a = new Integer(128); Integer b = new Integer(128); System.out.println("m22 result " + (a == b)); } }The print result is
m21 result falsem22 result false
a and b are still two objects
Javap parsing content
public void m21(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: bipush 100 6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 9: store_1 10: new #44; //class java/lang/Integer 13: dup 14: bipush 100 16: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 19: store_2 20: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 23: new #59; //class java/lang/StringBuilder 26: dup 27: ldc #84; //String m21 result 29: invokespecial #63; //Method 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; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 45: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 48: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 51: returnpublic void m22(); Code: 0: new #74; //class java/lang/Integer 3: dup 4: sipush 128 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 10: store_1 11: new #44; //class java/lang/Integer 14: dup 15: sipush 128 18: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 21: store_2 22: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 25: new #59; //class java/lang/StringBuilder 28: dup 29: ldc #86; //String m22 result 31: invokespecial #63; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 47: invokevirtual #70; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 47: invokevirtual #70; //Method java/lang/StringBuilder; 40: invokevirtual #70; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 47: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 50: invokevirtual #74; //Method 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; Integer b = 100; System.out.println("m31 result " + (a == b)); } public void m32() { Integer a = 128; Integer b = 128; System.out.println("m32 result " + (a == b)); } }Print results
m31 result truem32 result false
Why is there a first one true and a second one false? Observe the data parsed by Javap
Javap parsing content
public void m31(); Code: 0: bipush 100 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: store_1 6: bipush 100 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 11: store_2 12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 15: new #59; //class java/lang/StringBuilder 18: dup 19: ldc #88; //String m31 result 21: invokespecial #63; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 43: returnpublic void m32(); Code: 0: sipush 128 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 6: astore_1 7: sipush 128 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 13: store_2 14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 17: new #59; //class java/lang/StringBuilder 20: dup 21: ldc #90; //String m32 result 23: invokespecial #63; //Method 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; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: invokevirtual #74; //Method 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); Integer b = 100; System.out.println("m41 result " + (a == b)); } public void m42() { Integer a = Integer.valueOf(128); Integer b = 128; System.out.println("m42 result " + (a == b)); }}Print results
m41 result truem42 result false
Javap parsing content
public void m41(); Code: 0: bipush 100 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: store_1 6: bipush 100 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 11: store_2 12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 15: new #59; //class java/lang/StringBuilder 18: dup 19: ldc #92; //String m41 result 21: invokespecial #63; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 43: returnpublic void m42(); Code: 0: sipush 128 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 6: astore_1 7: sipush 128 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 13: store_2 14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream; 17: new #59; //class java/lang/StringBuilder 20: dup 21: ldc #94; //String m42 result 23: invokespecial #63; //Method 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; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder; 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 45: return}
analyze
Javap is a tool that comes with Java. It can be decompiled or viewed bytecode generated by the Java compiler (the above code only uses javap -c DataType). It is a good tool for analyzing code. For details, please Google it.
Let’s take a look at m4 first. Why does “true” appear in the running result? True means that a and b are the same object.
But object a is generated by calling Integer.valueOf(), and b is an object generated by automatic boxing. Why is it the same object? Let’s take a look at the bytecode again. After all, Java programs rely on virtual machines to run bytecode.
The m41 method only applies valueOf() once, but it appears twice in the bytecode, which means that valueOf() is also called during automatic boxing.
The following is the specific implementation of valueOf()
/** * Returns a <tt>Integer</tt> instance representing the specified * <tt>int</tt> value. * If a new <tt>Integer</tt> instance is not required, this method * should generally be used in preference to the constructor * {@link #Integer(int)}, as this method is likely to yield * significantly better space and time performance by caching * frequently requested values. * * @param i an <code>int</code> value. * @return a <tt>Integer</tt> instance representing <tt>i</tt>. * @since 1.5 */public static Integer valueOf(int i) {final int offset = 128;if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset];} return new Integer(i);}In numbers between [-128, 127], valueOf returns an object in the cache, so the two calls return the same object.
Thank you for reading, I hope it can help you. Thank you for your support for this site!