Java boxing and unboxing detailed explanation
Foreword:
To understand the concepts of boxing and unboxing, you must understand Java data types
Boxing: Primitive types are wrapped with their corresponding reference types, giving them the properties of objects. Int is packaged into Integer, float is packaged into Float
Unboxing: Contrary to boxing, reference type objects are simplified into value type data
Integer a = 100; 这是自动装箱 (编译器调用的是static Integer valueOf(int i)) int b = new Integer(100); 这是自动拆箱
Look at the following piece of 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 is the print result?
m11 result false m12 result false
"==" compares addresses, and the addresses of the two objects a and b are different, that is, they are two objects, so they are both false
Parse the 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: astore_1 10: bipush 100 12: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 15: astore_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/la ng/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/la ng/StringBuilder; 41: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 44: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 47: return public void m12(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: sipush 128 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 10: astore_1 11: sipush 128 14: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 17: astore_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."<init>":(Ljava/la ng/String;)V 30: aload_1 31: aload_2 32: if_acmpne 39 35: iconst_1 36: goto 40 39: iconst_0 40: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 43: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 46: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)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 false m22 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: astore_1 10: new #44; //class java/lang/Integer 13: dup 14: bipush 100 16: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 19: astore_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/la ng/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/la ng/StringBuilder; 45: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 48: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 51: return public void m22(); Code: 0: new #44; //class java/lang/Integer 3: dup 4: sipush 128 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 10: astore_1 11: new #44; //class java/lang/Integer 14: dup 15: sipush 128 18: invokespecial #46; //Method java/lang/Integer."<init>":(I)V 21: astore_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."<init>":(Ljava/la ng/String;)V 34: aload_1 35: aload_2 36: if_acmpne 43 39: iconst_1 40: goto 44 43: iconst_0 44: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 47: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 50: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)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)); } }
m31 result true m32 result false
public void m31(); Code: 0: bipush 100 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 5: astore_1 6: bipush 100 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 11: astore_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."<init>":(Ljava/la ng/String;)V 24: aload_1 25: aload_2 26: if_acmpne 33 29: iconst_1 30: goto 34 33: iconst_0 34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 43: return public void m32(); Code: 0: sipush 128 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 6: astore_1 7: sipush 128 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 13: astore_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/la ng/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/la ng/StringBuilder; 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 45: return
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 true m42 result false
##javap analysis content
public void m41(); Code: 0: bipush 100 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 5: astore_1 6: bipush 100 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 11: astore_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."<init>":(Ljava/la ng/String;)V 24: aload_1 25: aload_2 26: if_acmpne 33 29: iconst_1 30: goto 34 33: iconst_0 34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la ng/StringBuilder; 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 43: return public void m42(); Code: 0: sipush 128 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 6: astore_1 7: sipush 128 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In teger; 13: astore_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/la ng/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/la ng/StringBuilder; 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l ang/String; 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St ring;)V 45: return }
##Analysis
javap is a tool that comes with Java. It can decompile and view the bytecode generated by the Java compiler (the above code only uses javap -c DataType). It is a good tool for analyzing code. How to use it specifically Please Google it First look at m4, 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 object b is generated by automatic boxing. Why is it the same object? Let’s take a look at the bytecode again. After all, Java programs are implemented by relying on the virtual machine to run the bytecode. m41 This method only applies valueOf() once, but it appears twice in the bytecode, indicating that valueOf() is also called during autoboxing. 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); }