• 包装类的缓存问题


    整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。

          缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

          下面我们以Integer类为例,看一看Java为我们提供的源码,加深对缓存技术的理解,如示例8-7所示。

    【示例8-7】Integer类相关源码如下:

    1
    2
    3
    4
    5
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

          这段代码中我们需要解释下面几个问题:

          1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用。

          2. 一般情况下 IntegerCache.low为-128,IntegerCache.high为127,IntegerCache.cache为内部类的一个静态属性,如示例8-8所示。

    【示例8-8】IntegerCache类相关源码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
     
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }
        private IntegerCache() {}
    }

          由上面的源码我们可以看到,静态代码块的目的就是初始化数组cache的,这个过程会在类加载时完成。

          下面我们做一下代码测试,如示例8-9所示。

    【示例8-9】测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Test3 {
        public static void main(String[] args) {
            Integer in1 = -128;
            Integer in2 = -128;
            System.out.println(in1 == in2);//true 因为123在缓存范围内
            System.out.println(in1.equals(in2));//true
            Integer in3 = 1234;
            Integer in4 = 1234;
            System.out.println(in3 == in4);//false 因为1234不在缓存范围内
            System.out.println(in3.equals(in4));//true
        }
    }

          执行结果如图8-6所示:

    图8-6 示例8-9运行效果图.png

    图8-6 示例8-9运行效果图

          示例8-9的内存分析如图8-7所示:

    图8-7 示例8-9的内存分析图.png

    图8-7 示例8-9的内存分析图

    注意

          1. JDK1.5以后,增加了自动装箱与拆箱功能,如:

    1
    Integer i = 100;  int j = new Integer(100);

          2. 自动装箱调用的是valueOf()方法,而不是new Integer()方法。

          3. 自动拆箱调用的xxxValue()方法。

          4. 包装类在自动装箱时为了提高效率,对于-128~127之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用equals方法。

  • 相关阅读:
    有关try..catch..finally处理异常的总结
    java中finally和return的执行顺序
    慢查询处理
    阿里云数据库配置文件
    在DEV c++ 中如何设置默认的代码模板
    「C语言」单链表/双向链表的建立/遍历/插入/删除
    使用VS.NET2019做为C++开发专用IDE
    Windows下通过SSH无密码连接Linux服务器
    海沧区磁盘扩容思路办法
    Rabbitmq异常排查
  • 原文地址:https://www.cnblogs.com/huaxiansheng/p/15316106.html
Copyright © 2020-2023  润新知