一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

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

时间:2017-01-11 编辑:简简单单 来源:一聚教程网

Java 装箱与拆箱详解

前言:

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

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

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

Integer a =100;         这是自动装箱 (编译器调用的是staticInteger valueOf(inti))

int  b =newInteger(100); 这是自动拆箱

看下面一段代码

m1

publicclassDataType {

  

  publicstaticvoidmain(String args[]) {

    DataType dt =newDataType();

    dt.m11();

    dt.m12();

      

  }

  

  publicvoidm11() {

    Integer a =newInteger(100);

    Integer b =100;

    System.out.println("m11 result "+ (a == b));

  }

  

  publicvoidm12() {

    Integer a =newInteger(128);

    Integer b =128;

    System.out.println("m12 result "+ (a == b));

  }

  

    

}

  打印结果是什么?

m11 resultfalse

m12 resultfalse

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

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

publicvoidm11();

 Code:

  0: new  #44;//class java/lang/Integer

  3:  dup

  4:  bipush100

  6:  invokespecial  #46;//Method java/lang/Integer."":(I)V

  9:  astore_1

  10: bipush100

  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."":(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

  

publicvoidm12();

 Code:

  0: new  #44;//class java/lang/Integer

  3:  dup

  4:  sipush128

  7:  invokespecial  #46;//Method java/lang/Integer."":(I)V

  10: astore_1

  11: sipush128

  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."":(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

m2

publicclassDataType {

  

  publicstaticvoidmain(String args[]) {

    DataType dt =newDataType();

    dt.m21();

    dt.m22();

  }

  

  publicvoidm21() {

    Integer a =newInteger(100);

    Integer b =newInteger(100);

    System.out.println("m21 result "+ (a == b));

  }

  

  publicvoidm22() {

    Integer a =newInteger(128);

    Integer b =newInteger(128);

    System.out.println("m22 result "+ (a == b));

  }

  

    

}

  打印结果是

m21 resultfalse

m22 resultfalse

a和b仍是两个对象

javap解析内容

publicvoidm21();

 Code:

  0: new  #44;//class java/lang/Integer

  3:  dup

  4:  bipush100

  6:  invokespecial  #46;//Method java/lang/Integer."":(I)V

  9:  astore_1

  10:new  #44;//class java/lang/Integer

  13: dup

  14: bipush100

  16: invokespecial  #46;//Method java/lang/Integer."":(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."":(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

 

publicvoidm22();

 Code:

  0: new  #44;//class java/lang/Integer

  3:  dup

  4:  sipush128

  7:  invokespecial  #46;//Method java/lang/Integer."":(I)V

  10: astore_1

  11:new  #44;//class java/lang/Integer

  14: dup

  15: sipush128

  18: invokespecial  #46;//Method java/lang/Integer."":(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."":(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

publicclassDataType {

  

  publicstaticvoidmain(String args[]) {

    DataType dt =newDataType();

    dt.m31();

    dt.m32();

  }

  

  publicvoidm31() {

    Integer a =100;

    Integer b =100;

    System.out.println("m31 result "+ (a == b));

  }

  

  publicvoidm32() {

    Integer a =128;

    Integer b =128;

    System.out.println("m32 result "+ (a == b));

  }

  

  

}

  打印结果

m31 resulttrue

m32 resultfalse

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

javap解析内容

publicvoidm31();

 Code:

  0:  bipush100

  2:  invokestatic  #49;//Method java/lang/Integer.valueOf:(I)Ljava/lang/In

teger;

  5:  astore_1

  6:  bipush100

  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."":(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

 

publicvoidm32();

 Code:

  0:  sipush128

  3:  invokestatic  #49;//Method java/lang/Integer.valueOf:(I)Ljava/lang/In

teger;

  6:  astore_1

  7:  sipush128

  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."":(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

publicclassDataType {

  

  publicstaticvoidmain(String args[]) {

    DataType dt =newDataType();

    dt.m41();

    dt.m42();

  }

  

  

  publicvoidm41() {

    Integer a = Integer.valueOf(100);

    Integer b =100;

    System.out.println("m41 result "+ (a == b));

  }

    

  publicvoidm42() {

    Integer a = Integer.valueOf(128);

    Integer b =128;

    System.out.println("m42 result "+ (a == b));

  }

}

  打印结果

m41 resulttrue

m42 resultfalse

javap解析内容

publicvoidm41();

 Code:

  0:  bipush100

  2:  invokestatic  #49;//Method java/lang/Integer.valueOf:(I)Ljava/lang/In

teger;

  5:  astore_1

  6:  bipush100

  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   #92;//String m41 result

  21: invokespecial  #63;//Method java/lang/StringBuilder."":(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

 

publicvoidm42();

 Code:

  0:  sipush128

  3:  invokestatic  #49;//Method java/lang/Integer.valueOf:(I)Ljava/lang/In

teger;

  6:  astore_1

  7:  sipush128

  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   #94;//String m42 result

  23: invokespecial  #63;//Method java/lang/StringBuilder."":(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是Java自带的一个工具,可以反编译,也可以查看Java编译器生成的字节码(上面代码只使用了javap -c DataType),是分析代码的一个好工具,具体怎么使用请Google一下

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

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

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

下面是valueOf()具体实现

/**

 * Returns a Integer instance representing the specified

 * int value.

 * If a new Integer 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 int value.

 * @return a Integer instance representing i.

 * @since 1.5

 */

publicstaticInteger valueOf(inti) {

finalintoffset =128;

if(i >= -128&& i <=127) {// must cache

  returnIntegerCache.cache[i + offset];

}

  returnnewInteger(i);

}

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

热门栏目