一. 🦁 前言

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

二. 🦁 源码分析

1. valueOf(int i)

    @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

通过源码我们可知道,当参数i不在[IntegerCache.low , IntegerCache.high]范围内时,就直接实例化一个Integer对象并返回;否则返回IntegerCache类里面的cache数组里面的数据。
那么到这里,我们就能根据语义想得到了,Integer自动拆箱的缓存工作是由IntegerCache类完成的,咱们来点击查看一下这个类的工作原理。

2. IntegerCache类

我们查看这个类时,发现这个类是Integer的静态内部类,且定义了一个静态代码块,如下

  /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * jdk.internal.misc.VM class.
     */

    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 =
                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() {}
    }

这个静态内部类包含了三个变量:low,high,cache[]数组。

  1. 在静态代码块中,先通过VM.getSavedProperty()来获取high的值,检查"integerCacheHighPropValue"变量是否不为空,如果不为空,它尝试使用parseInt()方法将其解析为整数。如果解析成功,它将"i"的值设置为解析后的整数,并将其与127取最大值。然后它计算"h"变量的最大值,即"i"和Integer.MAX_VALUE减去负的"low"值再减1之间的较小值
    如果未设置属性值或无法将其解析为整数,则代码会优雅地忽略该属性,并继续使用默认值 127。
  1. 实例化cache数组的大小为 256,并且循环赋范围为[-128,127]的值进数组中。最后检查是否缓存全部的值(assert IntegerCache.high >= 127)。
  2. 最后构造私有的构造方法,以防止外部的类访问到IntegerCache。

三. 🦁 总结

这一期的Java基础复习到这里,咱们下一期见!!!

06-20 22:40