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

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

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

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

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

Integer a = 100;                  这是自动装箱  (编译器调用的是static Integer valueOf(int i)调用valueOf 是装箱)
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/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

 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/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
复制代码

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/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
复制代码

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/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     #92; //String m41 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 m42();
  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     #94; //String m42 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是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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值