在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

Java 装箱与拆箱详解及实例代码

2017-3-7 12:51| 发布者: zhangjf| 查看: 1776| 评论: 0

摘要: Java 装箱与拆箱详解 前言: 要理解装箱和拆箱的概念,就要理解Java数据类型 装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float 拆箱:和装箱相反,将引用类 ...

Java 装箱与拆箱详解

前言:

要理解装箱和拆箱的概念,就要理解Java数据类型

装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float

拆箱:和装箱相反,将引用类型的对象简化成值类型的数据

  1. Integer a = 100; 这是自动装箱 (编译器调用的是static Integer valueOf(int i))
  2. int b = new Integer(100); 这是自动拆箱
复制代码

看下面一段代码

m1

  1. public class DataType {
  2. public static void main(String args[]) {
  3. DataType dt = new DataType();
  4. dt.m11();
  5. dt.m12();
  6. }
  7. public void m11() {
  8. Integer a = new Integer(100);
  9. Integer b = 100;
  10. System.out.println("m11 result " + (a == b));
  11. }
  12. public void m12() {
  13. Integer a = new Integer(128);
  14. Integer b = 128;
  15. System.out.println("m12 result " + (a == b));
  16. }
  17. }
复制代码

  打印结果是什么?

  1. m11 result false
  2. m12 result false
复制代码

“==”比较的是地址,而a和b两个对象的地址不同,即是两个对象,所以都是false

通过javap解析字节码,内容如下

  1. public void m11();
  2. Code:
  3. 0: new #44; //class java/lang/Integer
  4. 3: dup
  5. 4: bipush 100
  6. 6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
  7. 9: astore_1
  8. 10: bipush 100
  9. 12: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  10. teger;
  11. 15: astore_2
  12. 16: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  13. 19: new #59; //class java/lang/StringBuilder
  14. 22: dup
  15. 23: ldc #61; //String m11 result
  16. 25: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  17. ng/String;)V
  18. 28: aload_1
  19. 29: aload_2
  20. 30: if_acmpne 37
  21. 33: iconst_1
  22. 34: goto 38
  23. 37: iconst_0
  24. 38: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  25. ng/StringBuilder;
  26. 41: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  27. ang/String;
  28. 44: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  29. ring;)V
  30. 47: return
  31. public void m12();
  32. Code:
  33. 0: new #44; //class java/lang/Integer
  34. 3: dup
  35. 4: sipush 128
  36. 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
  37. 10: astore_1
  38. 11: sipush 128
  39. 14: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  40. teger;
  41. 17: astore_2
  42. 18: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  43. 21: new #59; //class java/lang/StringBuilder
  44. 24: dup
  45. 25: ldc #82; //String m12 result
  46. 27: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  47. ng/String;)V
  48. 30: aload_1
  49. 31: aload_2
  50. 32: if_acmpne 39
  51. 35: iconst_1
  52. 36: goto 40
  53. 39: iconst_0
  54. 40: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  55. ng/StringBuilder;
  56. 43: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  57. ang/String;
  58. 46: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  59. ring;)V
  60. 49: return
  61. </init></init></init></init>
  62.  
复制代码

m2

  1. public class DataType {
  2. public static void main(String args[]) {
  3. DataType dt = new DataType();
  4. dt.m21();
  5. dt.m22();
  6. }
  7. public void m21() {
  8. Integer a = new Integer(100);
  9. Integer b = new Integer(100);
  10. System.out.println("m21 result " + (a == b));
  11. }
  12. public void m22() {
  13. Integer a = new Integer(128);
  14. Integer b = new Integer(128);
  15. System.out.println("m22 result " + (a == b));
  16. }
  17. }
复制代码

  打印结果是

  1. m21 result false
  2. m22 result false
复制代码

a和b仍是两个对象

javap解析内容

  1. public void m21();
  2. Code:
  3. 0: new #44; //class java/lang/Integer
  4. 3: dup
  5. 4: bipush 100
  6. 6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
  7. 9: astore_1
  8. 10: new #44; //class java/lang/Integer
  9. 13: dup
  10. 14: bipush 100
  11. 16: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
  12. 19: astore_2
  13. 20: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  14. 23: new #59; //class java/lang/StringBuilder
  15. 26: dup
  16. 27: ldc #84; //String m21 result
  17. 29: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  18. ng/String;)V
  19. 32: aload_1
  20. 33: aload_2
  21. 34: if_acmpne 41
  22. 37: iconst_1
  23. 38: goto 42
  24. 41: iconst_0
  25. 42: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  26. ng/StringBuilder;
  27. 45: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  28. ang/String;
  29. 48: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  30. ring;)V
  31. 51: return
  32. public void m22();
  33. Code:
  34. 0: new #44; //class java/lang/Integer
  35. 3: dup
  36. 4: sipush 128
  37. 7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
  38. 10: astore_1
  39. 11: new #44; //class java/lang/Integer
  40. 14: dup
  41. 15: sipush 128
  42. 18: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
  43. 21: astore_2
  44. 22: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  45. 25: new #59; //class java/lang/StringBuilder
  46. 28: dup
  47. 29: ldc #86; //String m22 result
  48. 31: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  49. ng/String;)V
  50. 34: aload_1
  51. 35: aload_2
  52. 36: if_acmpne 43
  53. 39: iconst_1
  54. 40: goto 44
  55. 43: iconst_0
  56. 44: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  57. ng/StringBuilder;
  58. 47: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  59. ang/String;
  60. 50: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  61. ring;)V
  62. 53: return
复制代码

m3

  1. public class DataType {
  2. public static void main(String args[]) {
  3. DataType dt = new DataType();
  4. dt.m31();
  5. dt.m32();
  6. }
  7. public void m31() {
  8. Integer a = 100;
  9. Integer b = 100;
  10. System.out.println("m31 result " + (a == b));
  11. }
  12. public void m32() {
  13. Integer a = 128;
  14. Integer b = 128;
  15. System.out.println("m32 result " + (a == b));
  16. }
  17. }
复制代码

  打印结果

  1. m31 result true
  2. m32 result false
复制代码

为什么有第一个是true,第二个是false呢?观察javap解析的数据

javap解析内容

  1. public void m31();
  2. Code:
  3. 0: bipush 100
  4. 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  5. teger;
  6. 5: astore_1
  7. 6: bipush 100
  8. 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  9. teger;
  10. 11: astore_2
  11. 12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  12. 15: new #59; //class java/lang/StringBuilder
  13. 18: dup
  14. 19: ldc #88; //String m31 result
  15. 21: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  16. ng/String;)V
  17. 24: aload_1
  18. 25: aload_2
  19. 26: if_acmpne 33
  20. 29: iconst_1
  21. 30: goto 34
  22. 33: iconst_0
  23. 34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  24. ng/StringBuilder;
  25. 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  26. ang/String;
  27. 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  28. ring;)V
  29. 43: return
  30. public void m32();
  31. Code:
  32. 0: sipush 128
  33. 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  34. teger;
  35. 6: astore_1
  36. 7: sipush 128
  37. 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  38. teger;
  39. 13: astore_2
  40. 14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  41. 17: new #59; //class java/lang/StringBuilder
  42. 20: dup
  43. 21: ldc #90; //String m32 result
  44. 23: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  45. ng/String;)V
  46. 26: aload_1
  47. 27: aload_2
  48. 28: if_acmpne 35
  49. 31: iconst_1
  50. 32: goto 36
  51. 35: iconst_0
  52. 36: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  53. ng/StringBuilder;
  54. 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  55. ang/String;
  56. 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  57. ring;)V
  58. 45: return
复制代码

m4

  1. public class DataType {
  2. public static void main(String args[]) {
  3. DataType dt = new DataType();
  4. dt.m41();
  5. dt.m42();
  6. }
  7. public void m41() {
  8. Integer a = Integer.valueOf(100);
  9. Integer b = 100;
  10. System.out.println("m41 result " + (a == b));
  11. }
  12. public void m42() {
  13. Integer a = Integer.valueOf(128);
  14. Integer b = 128;
  15. System.out.println("m42 result " + (a == b));
  16. }
  17. }
复制代码

  打印结果

  1. m41 result true
  2. m42 result false
复制代码

javap解析内容

  1. public void m41();
  2. Code:
  3. 0: bipush 100
  4. 2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  5. teger;
  6. 5: astore_1
  7. 6: bipush 100
  8. 8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  9. teger;
  10. 11: astore_2
  11. 12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  12. 15: new #59; //class java/lang/StringBuilder
  13. 18: dup
  14. 19: ldc #92; //String m41 result
  15. 21: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  16. ng/String;)V
  17. 24: aload_1
  18. 25: aload_2
  19. 26: if_acmpne 33
  20. 29: iconst_1
  21. 30: goto 34
  22. 33: iconst_0
  23. 34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  24. ng/StringBuilder;
  25. 37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  26. ang/String;
  27. 40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  28. ring;)V
  29. 43: return
  30. public void m42();
  31. Code:
  32. 0: sipush 128
  33. 3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  34. teger;
  35. 6: astore_1
  36. 7: sipush 128
  37. 10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
  38. teger;
  39. 13: astore_2
  40. 14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
  41. 17: new #59; //class java/lang/StringBuilder
  42. 20: dup
  43. 21: ldc #94; //String m42 result
  44. 23: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
  45. ng/String;)V
  46. 26: aload_1
  47. 27: aload_2
  48. 28: if_acmpne 35
  49. 31: iconst_1
  50. 32: goto 36
  51. 35: iconst_0
  52. 36: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
  53. ng/StringBuilder;
  54. 39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
  55. ang/String;
  56. 42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
  57. ring;)V
  58. 45: return
  59. }
复制代码

分析

javap是Java自带的一个工具,可以反编译,也可以查看Java编译器生成的字节码(上面代码只使用了javap -c DataType),是分析代码的一个好工具,具体怎么使用请Google一下

先看一下m4,为什么运行结果中出现了“true”呢,true说明a、b是同一个对象。 

但a对象是调用Integer.valueOf()生成的,b是通过自动装箱生成的对象,为什么会是同一个对象呢?再看一下字节码吧,毕竟java程序是依靠虚拟机运行字节码实现的。

m41这个方法只适用了一次valueOf(),但字节码中出现了两次,说明自动装箱时也调用了valueOf()。

下面是valueOf()具体实现

  1. /**
  2. * Returns a <tt>Integer</tt> instance representing the specified
  3. * <tt>int</tt> value.
  4. * If a new <tt>Integer</tt> instance is not required, this method
  5. * should generally be used in preference to the constructor
  6. * {[url=home.php?mod=space&uid=17823]@LINK[/url] #Integer(int)}, as this method is likely to yield
  7. * significantly better space and time performance by caching
  8. * frequently requested values.
  9. *
  10. * @param i an <code>int</code> value.
  11. * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
  12. * @since 1.5
  13. */
  14. public static Integer valueOf(int i) {
  15. final int offset = 128;
  16. if (i >= -128 && i <= 127) { // must cache
  17. return IntegerCache.cache[i + offset];
  18. }
  19. return new Integer(i);
  20. }
复制代码

在【-128,127】之间的数字,valueOf返回的是缓存中的对象,所以两次调用返回的是同一个对象。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-5-3 13:10

Copyright 2015-2025 djqfx

返回顶部