JDK5.0 之后提供了一种新特性:自动装箱拆箱。
既然是装拆箱,那么我们先来看看这个所谓的“箱”:
java中的8种基本数据类型都有与之对应的封装类(封装类就是所谓的箱)。分别是:
byte short int long double float char bool
Byte Short Integer Long Double Float Character Boolean
这一点上一篇文章也提到了。
这里说句题外话:为什么要有封装类?因为java是面向对象的语言,一切皆对象。有些时候最好甚至必须使用对象,然而基本数据类型并不是对象,所以封装类便解决了这个问题,把基本数据类型封装到对应的封装类中成为一个对象。(注:JDK5.0之后才产生的封装类以及装箱拆箱等特性。)
装箱拆箱很形象的说明了这一操作的动作是怎样的。即:装箱就是把基本数据类型封装到箱子里(封装成与之对应的封装类而成为一个实例),拆箱就是把一个实例从箱子里拿出来。
在JDK5.0之前
1 Integer a = 1;
如果这样写是错误的(类型转换错误)。然而现在JVM会自动做一些必要的操作,使得上面的不用new关键字实例化Integer对象而是直接赋上一个常数的操作合理。好比把一件东西装到一个箱子里(封装类的对象),这就是自动装箱。
反之:
1 Integer b = new Integer(1); 2 int c = b;
把一个Integer的对象b直接赋值给int变量c,JVM默认会取出b的值赋给c,就好像从箱子里拿出一件东西给了谁谁谁,这就是自动拆箱。
而且不管是装箱还是拆箱,你都不必操心这是是怎么做的,JVM会搞定这些。换句话说,你只要知道可以这样赋值就好:Integer a = 1;。除非你想知其然亦知其所以然。其中:装箱操作默认调用的是Integer的静态方法valueOf,拆箱操作默认调用的是Integer的intValue方法。下面是jdk1.6.0_10文档中Integer类的源码:
valueOf:
1 public static Integer valueOf(int i){ 2 final int offset = 128; 3 if (i >= -128 && i <= 127) { // must cache 4 return IntegerCache.cache[i + offset]; 5 } 6 return new Integer(i); 7 }
intValue:
1 public int intValue(){ 2 return value; 3 }
至于其中的IntegerCache,是因为JVM的优化和常量池技术,使得Integer类在用Integer a = 1; 这样的方式声明变量时,当赋予的值在-128-127之间时,会在实例化的同时将引用加入到常量池中以便以后的操作中可以从常量池中获取这个值,减少了资源的浪费,也减少了对内存的操作使系统速度相对快一些。