Java 裝箱與拆箱詳解
前言:
要理解裝箱和拆箱的概念,就要理解Java資料型別
裝箱:把基本型別用它們對應的引用型別包裝起來,使其具有對象的性質。 int包裝成Integer、float包裝成Float
拆箱:和裝箱相反,將引用類型的物件簡化成值類型的資料
1 2 | Integer a = 100; 这是自动装箱 (编译器调用的是 static Integer valueOf(int i))
int b = new Integer(100); 这是自动拆箱
|
登入後複製
列印結果是什麼?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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));
}
}
|
登入後複製
「==」比較的是位址,而a和b兩個物件的位址不同,即是兩個對象,所以都是false
透過javap解析字節碼,內容如下
1 2 | m11 result false
m12 result false
|
登入後複製
m2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | public void m11();
Code:
0: new #44;
3: dup
4: bipush 100
6: invokespecial #46;
9: astore_1
10: bipush 100
12: invokestatic #49;
teger;
15: astore_2
16: getstatic #53;
19: new #59;
22: dup
23: ldc #61;
25: invokespecial #63;
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;
ng/StringBuilder;
41: invokevirtual #70;
ang/String;
44: invokevirtual #74;
ring;)V
47: return
public void m12();
Code:
0: new #44;
3: dup
4: sipush 128
7: invokespecial #46;
10: astore_1
11: sipush 128
14: invokestatic #49;
teger;
17: astore_2
18: getstatic #53;
21: new #59;
24: dup
25: ldc #82;
27: invokespecial #63;
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;
ng/StringBuilder;
43: invokevirtual #70;
ang/String;
46: invokevirtual #74;
ring;)V
49: return
</init></init></init></init>
|
登入後複製
〜<
javap解析內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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));
}
}
|
登入後複製
m3
1 2 | m21 result false
m22 result false
|
登入後複製
列印結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | public void m21();
Code:
0: new #44;
3: dup
4: bipush 100
6: invokespecial #46;
9: astore_1
10: new #44;
13: dup
14: bipush 100
16: invokespecial #46;
19: astore_2
20: getstatic #53;
23: new #59;
26: dup
27: ldc #84;
29: invokespecial #63;
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;
ng/StringBuilder;
45: invokevirtual #70;
ang/String;
48: invokevirtual #74;
ring;)V
51: return
public void m22();
Code:
0: new #44;
3: dup
4: sipush 128
7: invokespecial #46;
10: astore_1
11: new #44;
14: dup
15: sipush 128
18: invokespecial #46;
21: astore_2
22: getstatic #53;
25: new #59;
28: dup
29: ldc #86;
31: invokespecial #63;
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;
ng/StringBuilder;
47: invokevirtual #70;
ang/String;
50: invokevirtual #74;
ring;)V
53: return
|
登入後複製
為什麼有第一個是true,第二個是false呢?觀察javap解析的資料
javap解析內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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));
}
}
|
登入後複製
m4
1 2 | m31 result true
m32 result false
|
登入後複製
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | public void m31();
Code:
0: bipush 100
2: invokestatic #49;
teger;
5: astore_1
6: bipush 100
8: invokestatic #49;
teger;
11: astore_2
12: getstatic #53;
15: new #59;
18: dup
19: ldc #88;
21: invokespecial #63;
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;
ng/StringBuilder;
37: invokevirtual #70;
ang/String;
40: invokevirtual #74;
ring;)V
43: return
public void m32();
Code:
0: sipush 128
3: invokestatic #49;
teger;
6: astore_1
7: sipush 128
10: invokestatic #49;
teger;
13: astore_2
14: getstatic #53;
17: new #59;
20: dup
21: ldc #90;
23: invokespecial #63;
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;
ng/StringBuilder;
39: invokevirtual #70;
ang/String;
42: invokevirtual #74;
ring;)V
45: return
|
登入後複製
javap解析內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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));
}
}
|
登入後複製
分析
javap是Java自帶的一個工具,可以反編譯,也可以查看Java編譯器產生的字節碼(上面程式碼只使用了javap -c DataType),是分析程式碼的一個好工具,具體怎麼使用請Google一下
先看一下m4,為什麼運行結果中出現了「true」呢,true說明a、b是同一個物件。
但a對像是呼叫Integer.valueOf()產生的,b是透過自動裝箱產生的對象,為什麼會是同一個對象呢?再看一下字節碼吧,畢竟Java程式是靠虛擬機器來運行字節碼來實現的。
m41這個方法只適用了一次valueOf(),但字節碼中出現了兩次,表示自動裝箱時也呼叫了valueOf()。
下面是valueOf()具體實作
1 2 | m41 result true
m42 result false
|
登入後複製
在【-128,127】之間的數字,valueOf回傳的是快取中的物件,所以兩次呼叫返回的是同一個物件。
感謝閱讀,希望能幫助大家,謝謝大家對本站的支持!
更多Java 裝箱與拆箱詳解及實例代碼相關文章請關注PHP中文網!