当前位置: 首页 > article >正文

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

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

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一块测试,效果如下:

false
true
true
false

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

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

    /**
     * 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的源码:

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


http://www.kler.cn/a/312012.html

相关文章:

  • 使用Python实现对接Hadoop集群(通过Hive)并提供API接口
  • 宗馥莉的接班挑战:内斗升级,竞品“偷家”
  • 爬虫补环境案例---问财网(rpc,jsdom,代理,selenium)
  • 基于springboot的汽车租赁管理系统的设计与实现
  • 量化交易系统开发-实时行情自动化交易-3.4.2.2.Okex交易数据
  • 传奇996_21——龙岭事件
  • 旧系统迁移新框架:FastAPI 的 WSGIMiddleware 让过程变得简单
  • 松材线虫无人机数据集——20731个,已人工标注出来的样本【深度学习样本】
  • 【Leetcode:2848. 与车相交的点 + 模拟计数】
  • Java | Leetcode Java题解之第413题等差数列划分
  • 最新!综合性SCI期刊汇总!《NATURE》位居榜首~
  • 大数据基础架构技术栈一览
  • Redis 的三个并发问题及解决方案(面试题)
  • 【AI大模型】ChatGPT模型原理介绍(下)
  • Redis 执行 Lua,能保证原子性吗?
  • 深入解析 JVM 中静态块、静态属性、构造块与构造方法的执行顺序
  • Vue2项目升级攻略:如何更新package.json中的依赖
  • WPF 中的线程池
  • 阿里云盘照片事件!网络安全警钟长鸣
  • 网站采用H5+CSS3开发的优势和劣势
  • postgresql-patroni高可用安装部署
  • 中国电子学会202306青少年软件编程(Python)等级考试试卷(二级)真题
  • Kubernetes调度基础
  • 二叉树的遍历【C++】
  • python批量对遥感影像进行归一化与数据清洗
  • 【Linux】—— muduo网络库的安装配置与使用