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!