黑马程序员-java自动装箱于拆箱

原创 2015年05月14日 21:26:06

——- android培训java培训、期待与您交流! ———-自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象。自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接。

你不能直接地向集合(Collections)中放入原始类型值,因为集合只接收对象。通常这种情况下你的做法是,将这些原始类型的值转换成对象,然后将这些转换的对象放入集合中。使用Integer,Double,Boolean等这些类我们可以将原始类型值转换成对应的对象,但是从某些程度可能使得代码不是那么简洁精炼。为了让代码简练,Java 1.5引入了具有在原始类型和对象类型自动转换的装箱和拆箱机制。但是自动装箱和拆箱并非完美,在使用时需要有一些注意事项,如果没有搞明白自动装箱和拆箱,可能会引起难以察觉的bug。

什么是自动装箱和拆箱

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte,short,char,int,long,float,double和boolean对应的封装类为Byte,Short,Character,Integer,Long,Float,Double,Boolean。

自动装箱拆箱要点

自动装箱时编译器调用valueOf将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值。
自动装箱是将boolean值转换成Boolean对象,byte值转换成Byte对象,char转换成Character对象,float值转换成Float对象,int转换成Integer,long转换成Long,short转换成Short,自动拆箱则是相反的操作。
何时发生自动装箱和拆箱

自动装箱和拆箱在Java中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动讲这个原始类型值转换成与之对应的对象。最经典的一个场景就是当我们向ArrayList这样的容器中增加原始类型数据时或者是创建一个参数化的类,比如下面的ThreadLocal。

ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1); //autoboxing - primitive to object
intList.add(2); //autoboxing

ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>();
intLocal.set(4); //autoboxing

int number = intList.get(0); // unboxing
int local = intLocal.get(); // unboxing in Java

举例说明

上面的部分我们介绍了自动装箱和拆箱以及它们何时发生,我们知道了自动装箱主要发生在两种情况,一种是赋值时,另一种是在方法调用的时候。为了更好地理解这两种情况,我们举例进行说明。

赋值时

这是最常见的一种情况,在Java 1.5以前我们需要手动地进行转换才行,而现在所有的转换都是由编译器来完成。

//before autoboxing
Integer iObject = Integer.valueOf(3);
Int iPrimitive = iObject.intValue()

//after java5
Integer iObject = 3; //autobxing - primitive to wrapper conversion
int iPrimitive = iObject; //unboxing - object to primitive conversion

方法调用时

这是另一个常用的情况,当我们在方法调用时,我们可以传入原始数据值或者对象,同样编译器会帮我们进行转换。

public static Integer show(Integer iParam){
   System.out.println("autoboxing example - method invocation i: " + iParam);
   return iParam;
}

//autoboxing and unboxing in method invocation
show(3); //autoboxing
int result = show(3); //unboxing because return type of method is Integer

show方法接受Integer对象作为参数,当调用show(3)时,会将int值转换成对应的Integer对象,这就是所谓的自动装箱,show方法返回Integer对象,而int result = show(3);中result为int类型,所以这时候发生自动拆箱操作,将show方法的返回的Integer对象转换成int值。

自动装箱的弊端

自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;
 for(int i=1000; i<5000; i++){
   sum+=i;
}

上面的代码sum+=i可以看成sum = sum + i,但是+这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下

sum = sum.intValue() + i;
Integer sum = new Integer(result);

由于我们这里声明的sum为Integer类型,在上面的循环中会创建将近4000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。

重载与自动装箱

当重载遇上自动装箱时,情况会比较有些复杂,可能会让人产生有些困惑。在1.5之前,value(int)和value(Integer)是完全不相同的方法,开发者不会因为传入是int还是Integer调用哪个方法困惑,但是由于自动装箱和拆箱的引入,处理重载方法时稍微有点复杂。一个典型的例子就是ArrayList的remove方法,它有remove(index)和remove(Object)两种重载,我们可能会有一点小小的困惑,其实这种困惑是可以验证并解开的,通过下面的例子我们可以看到,当出现这种情况时,不会发生自动装箱操作。

public void test(int num){
    System.out.println("method with primitive argument");

}

public void test(Integer num){
    System.out.println("method with wrapper argument");

}

//calling overloaded method
AutoboxingTest autoTest = new AutoboxingTest();
int value = 3;
autoTest.test(value); //no autoboxing 
Integer iValue = value;
autoTest.test(iValue); //no autoboxing

Output:
method with primitive argument
method with wrapper argument

相关文章推荐

黑马程序员<Java 1.5新特性>静态导入、增强for、可变参数、自动装箱拆箱、枚举

一、静态导入(static import)   1、静态导入的与普通import的区别:     import语句可以导入一个类,或者包中的类;     import static 语句可以导入一个类...

黑马程序员-java1.5自动装箱与拆箱

1.什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。  一般我们要创建一个类的对象的时候,我们会这样: ...

黑马程序员 Java高新技术(eclipse的使用,静态导入,可变参数,增强for,自动拆箱与装箱)

------- android培训、java培训、java学习型技术博客、期待与您交流! ---------- eclipse的使用 IDE(Integrated Developmen...

黑马程序员——Java1.5新特性之享元模式、增强for循环、可变参数、静态导入、自动装箱和拆箱

---------------------- android培训、java培训、期待与您交流! ---------------------- 享元模式是构造型模式之一,通过与其他类似的对象共享相同数...
  • cds885
  • cds885
  • 2012年03月05日 21:33
  • 595

《黑马程序员》java笔记->基本数据类型包装类及自动拆箱装箱原理,数组排序练习字符串切割

------- android培训、java培训、期待与您交流! ---------- /* * 基本数据类型对象包装类。 *  * 想要对基本类型数据进行更多的操作,最方...
  • bb175pt
  • bb175pt
  • 2013年06月16日 17:37
  • 1053

黑马程序员-Java的自动拆箱和装箱

---------------------- android培训、java培训、期待与您交流! ---------------------- Java1.5引入了其中一个新特性就是自动装箱和拆箱...

黑马程序员 java高级技术1.5之自动装箱和拆箱(张孝祥)

public class AutoBox { /** * 1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, * 如果两个变量是基本类型的,那很容易,直接比较值就可以了...

黑马程序员----静态导入,for each循环,自动装箱拆箱学习日志

---------------------- android培训、java培训、期待与您交流! -------------------------   静态导入: import static...
  • imabra
  • imabra
  • 2011年11月25日 10:48
  • 305

黑马程序员-jdk1.5新特性--基本数据类型的自动拆箱与装箱

自动装箱:   Interger num1=12;自动拆箱  System.out.println(num1+12); 基本数据类型的对象缓存:  Integer num1=12;  Integer ...
  • laladin
  • laladin
  • 2011年07月09日 16:06
  • 211

黑马程序员 十四、Eclipse 的使用、增强 for 循环、自动拆箱与装箱等

Java帮帮-IT资源分享网 1、Eclipse 的使用技巧 eclipse 与 myeclipse 的关系(都属于 java 开发的工具): 后者是前者的一个插件,后来为了方便...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:黑马程序员-java自动装箱于拆箱
举报原因:
原因补充:

(最多只允许输入30个字)