Java装箱和拆箱的基本概念及使用

来源:互联网 发布:我的阿里云tv工程模式 编辑:程序博客网 时间:2024/04/29 20:14

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

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

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

Integer a = 100;                  这是自动装箱  (编译器调用的是static Integer valueOf(int i))
int     b = new Integer(100); 这是自动拆箱

看下面一段代码

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));
    }
 
     
}

  打印结果是什么?

m11 result false
m12 result false

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

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

public void m11();
  Code:
   0:   new     #44; //class java/lang/Integer
   3:   dup
   4:   bipush  100
   6:   invokespecial   #46; //Method java/lang/<span style="color: #ff0000;">Integer."<init>":(I)V</span>
   9:   astore_1
   10:  bipush  100
   12:  invokestatic    #49; //Method java/lang/<span style="color: #ff0000;">Integer.valueOf:(I)</span>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

 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));
    }
 
     
}

  打印结果是

m21 result false
m22 result false

a和b仍是两个对象

javap解析内容

复制代码
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/lang/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/lang/StringBuilder;   45:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   48:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V   51:  returnpublic 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/lang/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/lang/StringBuilder;   47:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   50:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)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));
    }
 
 
}

  打印结果

m31 result true
m32 result false

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

javap解析内容

复制代码
public void m31();  Code:   0:   bipush  100   2:   invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   5:   astore_1   6:   bipush  100   8:   invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   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/lang/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/lang/StringBuilder;   37:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   40:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V   43:  returnpublic void m32();  Code:   0:   sipush  128   3:   invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   6:   astore_1   7:   sipush  128   10:  invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   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/lang/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/lang/StringBuilder;   39:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   42:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V   45:  return
复制代码

m4

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));
    }
}

  打印结果

m41 result true
m42 result false

javap解析内容

复制代码
public void m41();  Code:   0:   bipush  100   2:   invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   5:   astore_1   6:   bipush  100   8:   invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   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."<init>":(Ljava/lang/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/lang/StringBuilder;   37:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   40:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)V   43:  returnpublic void m42();  Code:   0:   sipush  128   3:   invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   6:   astore_1   7:   sipush  128   10:  invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;   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."<init>":(Ljava/lang/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/lang/StringBuilder;   39:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   42:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/String;)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 <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);
}

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

【参考】http://jzinfo.iteye.com/blog/450590

    http://xiaoyu1985ban.iteye.com/blog/1384191

0 0