Java中Integer的缓存池是怎么实现的?

开始介绍之前,希望大家能想一想下面这串代码运行出来的结果是什么?

java 复制代码
public class IntegerCacheTest {

    public static void main(String[] args) {
        fun1();
        fun2();
        fun3();
        fun4();
    }

    public static void fun1(){
        Integer num1 = -129;
        Integer num2 = -129;
        System.out.println(num1 == num2);
    }

    public static void fun2(){
        Integer num1 = -128;
        Integer num2 = -128;
        System.out.println(num1 == num2);
    }

    public static void fun3(){
        Integer num1 = 127;
        Integer num2 = 127;
        System.out.println(num1 == num2);
    }

    public static void fun4(){
        Integer num1 = 128;
        Integer num2 = 128;
        System.out.println(num1 == num2);
    }
}

-129和-129的Integer对象,相不相等?使用基本数据类型int定义的值肯定相等,但是Integer是引用数据类型,而且-129不在缓存区里,所以应该是false。

-128在不在缓存区呢?把它和127,128一块测试,效果如下:

java 复制代码
false
true
true
false

从结果上看,说明128也并不在Integer的缓存区里。所以Integer的缓存范围是-128到127之间,并且包含两个边界值,一共256个数(别忘了有个0)。

下面对Integer的相关源码解析一下:

上面的代码Integer在创建对象时会使用到valueOf方法,下面来看一下这个方法:

java 复制代码
    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    @IntrinsicCandidate
    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和i <= IntegerCache.high的时候直接返回一个IntegerCache里缓存的数据,而不满足的条件则是直接new一个新的Integer。

下面查看一下IntegerCache的源码:

java 复制代码
    /**
     * 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.
     *
     * WARNING: The cache is archived with CDS and reloaded from the shared
     * archive at runtime. The archived cache (Integer[]) and Integer objects
     * reside in the closed archive heap regions. Care should be taken when
     * changing the implementation and the cache array should not be assigned
     * with new Integer object(s) after initialization.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer[] cache;
        static Integer[] archivedCache;

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    h = Math.max(parseInt(integerCacheHighPropValue), 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            // Load IntegerCache.archivedCache from archive, if possible
            CDS.initializeFromArchive(IntegerCache.class);
            int size = (high - low) + 1;

            // Use the archived cache if it exists and is large enough
            if (archivedCache == null || size > archivedCache.length) {
                Integer[] c = new Integer[size];
                int j = low;
                for(int i = 0; i < c.length; i++) {
                    c[i] = new Integer(j++);
                }
                archivedCache = c;
            }
            cache = archivedCache;
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

可以看到low是-128,high虽然并没有在定义的时候赋值,但是执行静态代码块的时候把127赋值给了high,这就是缓存的数据范围。通过代码分析,可以看到**static final Integer[] cache;**保存了从-128到127的数据,所以我们创建Integer对象时如果在这个区间,其实使用的都是缓存对象,所以使用==判断是true,反之为false,这边使用的是设计模式中的享元模式。

相关推荐
技术无疆26 分钟前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
2401_8582861128 分钟前
52.【C语言】 字符函数和字符串函数(strcat函数)
c语言·开发语言
铁松溜达py29 分钟前
编译器/工具链环境:GCC vs LLVM/Clang,MSVCRT vs UCRT
开发语言·网络
everyStudy29 分钟前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
C-SDN花园GGbond2 小时前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法
迷迭所归处3 小时前
C++ —— 关于vector
开发语言·c++·算法
码农郁郁久居人下3 小时前
Redis的配置与优化
数据库·redis·缓存
架构文摘JGWZ3 小时前
Java 23 的12 个新特性!!
java·开发语言·学习
leon6253 小时前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
拾光师4 小时前
spring获取当前request
java·后端·spring