首先我们来认识一下装箱,在我们平时代码里随处可见,只是你没有留意到罢了(准确来说是JDK没让你注意到),对于代码片段:
也都看到了,拆装箱其实也就这么回事(也有可能理解层次还不够
)。
Double d = 12d;
来说,这是我们写的java代码,还没有进行过编译,在jvm中运行前,编译器会做什么什么事呢,通过反编译工具我们可以看到其class文件内容:
Double d = Double.valueOf(12d);
我们再来看一下valueOf方法:
public static Double valueOf(double d) {
return new Double(d);
}
可以发现等于是new了一个Double对象,并把值“12”传给了这个对象d。
这就是我们老生常谈的“装箱”
那如果是:
Double d = 12d;
double i = d.doubleValue();
Long l = 12L;
Long ll = l.longValue();
Integer i = 12;
int in = i.intValue();
相信我们已经想到了,这就是所谓的拆箱。
下面象征性地总结一下:
- 基本数据类型,类似于double、long、int的值如12d、12L、12赋值给对象类型(也就是包装类型)Double、Long、Integer时,就是所谓的装箱,在“幕后”分别有Double.valueOf(12d)、Long.valueOf(12L)、Integer.valueOf(12)操作完成了装箱操作
- 对象类型(也就是包装类型),类似于d、l、i调用doubleValue()、longValue()、intValue()时,就完成了拆箱操作
- 特点:装箱...valueOf / 拆箱...Value
- 所谓自动,是指的编译器完成的,对编码者是“不可见的”,所以称之为自动
- 基本数据类型是存储在栈中的,而包装类型是直接在堆内存中开辟了一块存储空间
之所以会有包装类型出现(这里有个契机,在java1.5随泛型一起出现的),自然有它的道理,我们来看一下:
- 在从数据库中查询某条数据(如分数)并用基本类型int来接收时,如果该条记录的分数暂时还没有值(我们假设在数据库中该字段可以为null),那我们由于用int接收,虽然没有值,但是int默认初始值为0.而如果我们用Integer类型接收时,就可以表示为null了。
- 泛型中(你有见过后者么,这样就不言自明了吧):
Map<String, Integer> map = new HashMap<>(); Map<String, int> map = new HashMap<>();
- 包装类型自然可以当做一个类来使用,JDK中的类自然就有可以使用的便捷方法,为我们编码提供了便利。