zoukankan      html  css  js  c++  java
  • 基本数据类型及其包装类(二)

    上篇文章我们简单介绍了包装的相关基本概念,并简单分析了 Integer 类中的几个核心的方法源码,但是有关自动拆装箱的概念限于篇幅并没能完成介绍,本篇还将分析几种常见的包装类面试题,深入理解一下我们的包装类设计。

    自动拆装箱

    所谓「拆箱」就是指,包装类型转换为基本类型的过程,而所谓的「装箱」则是基本类型到包装类型的过程。例如:

    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 的实现比较特殊,因为它只有两种取值可能,其实也能够算作支持缓存功能的。


    文章中的所有代码、图片、文件都云存储在我的 GitHub 上:

    (https://github.com/SingleYam/overview_java)

    欢迎关注微信公众号:扑在代码上的高尔基,所有文章都将同步在公众号上。

    image

  • 相关阅读:
    Json对象与Json字符串互转(4种转换方式)
    Web.config配置文件详解
    jQuery BlockUI Plugin Demo 6(Options)
    jQuery BlockUI Plugin Demo 5(Simple Modal Dialog Example)
    jQuery BlockUI Plugin Demo 4(Element Blocking Examples)
    jQuery BlockUI Plugin Demo 3(Page Blocking Examples)
    jQuery BlockUI Plugin Demo 2
    <configSections> 位置引起的错误
    关于jQuery的cookies插件2.2.0版设置过期时间的说明
    jQuery插件—获取URL参数
  • 原文地址:https://www.cnblogs.com/yangming1996/p/8834525.html
Copyright © 2011-2022 走看看