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,这边使用的是设计模式中的享元模式。

相关推荐
qq_4419960529 分钟前
Mybatis官方生成器使用示例
java·mybatis
Qter_Sean31 分钟前
自己动手写Qt Creator插件
开发语言·qt
何曾参静谧35 分钟前
「QT」文件类 之 QIODevice 输入输出设备类
开发语言·qt
巨大八爪鱼36 分钟前
XP系统下用mod_jk 1.2.40整合apache2.2.16和tomcat 6.0.29,让apache可以同时访问php和jsp页面
java·tomcat·apache·mod_jk
爱吃生蚝的于勒2 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田3 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
小白学大数据4 小时前
Python爬虫开发中的分析与方案制定
开发语言·c++·爬虫·python
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
冰芒猓4 小时前
SpringMVC数据校验、数据格式化处理、国际化设置
开发语言·maven