首頁 > Java > java教程 > Java 裝箱與拆箱詳解及實例代碼

Java 裝箱與拆箱詳解及實例代碼

高洛峰
發布: 2017-01-24 14:13:08
原創
1613 人瀏覽過

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; //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>

登入後複製

   

 〜<

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; //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

登入後複製

   

為什麼有第一個是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; //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

登入後複製

   

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中文網!

相關標籤:
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板