在线咨询
QQ咨询
服务热线
服务热线:13125520620
TOP

基本数据类型及其包装类

发布时间:2018-4-14 浏览:3062

自动拆装箱
 
所谓「拆箱」就是指,包装类型转换为基本类型的过程,而所谓的「装箱」则是基本类型到包装类型的过程。例如:
 
public static void main(String[] args){
    int age = 21;
    Integer integer = new Integer(age);    //装箱
    int num = integer.intValue();          //拆箱
}
自从 jdk1.5 以后,引入了自动拆装箱的概念,上述代码可以简化成如下代码:
 
public static void main(String[] args){
    int age = 21;
    Integer integer = age;              //自动装箱
    int num = integer;                  //自动拆箱
}
是不是感觉简便了很多,但是实际上在 JVM 层面是没有变化的,这都是编译器做的「假象」。
 
image
 
只是编译器允许你这样书写代码了,其实编译成字节码指令的时候,编译器还是会调用相应的拆装箱方法的。
 
可以看到,拆装箱是需要方法调用的,也就是需要栈帧的入栈出栈的,直白点说,就是耗资源,所以我们的程序中应当尽量避免大量的「拆装箱」操作。
 
面试题
 
面试题一:
 
public static void main(String[] args){
    Integer i1 = 100;
    Integer i2 = 100;
    Integer i3 = 200;
    Integer i4 = 200;
 
    System.out.println(i1==i2);
    System.out.println(i3==i4);
}
如果之前没了解过 Integer 内部源码的人想必会对输出的结果「百思不得其解」。
 
输出结果为:
 
true
false
如果你认真看完了我的两篇文章,这个问题应该不难解释。
 
直接将整型数值赋值给 Integer 实例将发生装箱操作,也就是调用 valueOf 方法,而这个方法我们分析过,会首先检查一下 100 是否在缓存池是否缓存了,当然 IntegerCache 会默认缓存 [-128,127] 之间的 Integer 实例,所以这里会直接从缓存池中取出引用赋值给变量 i1 。
 
同理 i2 也会从缓存池中取引用,并且两者的引用的是同一个堆对象,所以才会输出 「true」。
 
而第二个输出「false」也是很好理解的,因为 200 不再缓存池缓存的范围内,所以每次调用 valueOf 方法都会新建一个不同的 Integer 实例。
 
面试题二:
 
public static void main(String[] args){
    Double i1 = 100.0;
    Double i2 = 100.0;
    Double i3 = 200.0;
    Double i4 = 200.0;
 
    System.out.println(i1==i2);
    System.out.println(i3==i4);
}
很多人会认为这段代码的输出结果会和上题一样,但是其实不然:
 
false
false
那是因为 Double 这个包装类并没有缓存池的概念,也就是说它会为每一个 double 型数值包装一个新的 Double 实例。正如它的 valueOf 方法:
 
public static Double valueOf(double d) {
    return new Double(d);
}
这里可能有人会疑问了,为什么 Integer 用缓存池提升效率,而 Double 却弃之不用呢?
 
其实也很简单,你会发现 IntegerCache 是用 Integer 数组缓存了某个区间的所有数值对应的 Integer 实例,那么请问给定一个区间 [-128.0,127.0],你能确定之中有多少个 double 数值吗?
 
因为任意一个区间,哪怕再小的区间都对应的无穷尽的 double 小数,所以无法进行缓存。
 
同样的问题也适用于 Float。
 
面试题三:
 
public static void main(String[] args){
    Boolean i1 = false;
    Boolean i2 = false;
    Boolean i3 = true;
    Boolean i4 = true;
 
    System.out.println(i1==i2);
    System.out.println(i3==i4);
}
输出结果:
 
true
true
Boolean 的 valueOf 方法是这样的:
 
public static final Boolean TRUE = new Boolean(true);
 
public static final Boolean FALSE = new Boolean(false);
 
public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}
显然,结果相信不再需要多做解释了。
 
最后需要提一下的是,八种包装类中有以下五种是支持「缓存池」的。
 
Integer:对应的缓存池类型为 IntegerCache
Byte:对应的缓存池类型为 ByteCache
Short:对应的额缓存池类型为 ShortCache
Long:对应的额缓存池类型为 LongCache
Character:对应的缓存池类型为 CharacterCache
其实 Boolean 的实现比较特殊,因为它只有两种取值可能,其实也能够算作支持缓存功能的。
软件定制,软件开发,友情提醒。

TAG
软件定制,软件开发,瀚森HANSEN
0
该内容对我有帮助