Java packing and unpacking details and example code

  • 2020-05-27 05:38:34
  • OfStack

Java packing and unpacking details

Preface:

To understand the concepts of boxing and unboxing, you need to understand the Java data type

Boxed: basic types are wrapped with their corresponding reference types to give them the properties of objects. int is packaged as Integer, float as Float

Unboxing: as opposed to boxing, objects of reference types are reduced to data of value types


Integer a = 100;          This is autoboxing  ( The compiler calls static Integer valueOf(int i))
int   b = new Integer(100);  This is automatic unpacking 

Take a 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 the address, while a and b have different addresses, that is, they are two objects, so they are both false

The bytecode is parsed by javap 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 printout is


m21 result false
m22 result false

a and b are still two objects

javap parses the 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));
  }
 
 
}

Print the result


m31 result true
m32 result false

Why is the first one true and the second one false? Observe the data parsed by javap

javap parses the content


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

m4


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));
  }
 
   
}
0

Print the result


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));
  }
 
   
}
1

javap parses the content


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));
  }
 
   
}
2

Analysis of the

javap is a tool that comes with Java, which can be decompiled, and can also view the bytecode generated by Java compiler (the above code only USES javap-c DataType), which is a good tool for analyzing code. How to use Google1

First look at m4, why "true" appears in the running result? true indicates that a and b are the same object.

But the a object is generated by calling Integer.valueOf (), and b is generated by autoboxing. Why is it the same object? Take another look at the bytecode. After all, the Java program relies on a virtual machine to run the bytecode.

m41 only worked once for valueOf(), but twice in the bytecode, indicating that valueOf() was also called during autoboxing.

Below is the 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);
}

The number between [-128, 127], valueOf returns the object in the cache, so both calls return the same object.

Thank you for reading, I hope to help you, thank you for your support of this site!


Related articles: