JAVA包装类型缓存池详解

本文深入探讨了Java中基本类型缓存池的工作原理,包括自动装箱拆箱机制,以及Integer缓存池的具体实现和源码分析。了解如何利用缓存池提升程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:我们知道,缓存一些常用的数据能提高程序的运行效率,而在Java中,Java给一些基本类型提供了一个缓存池,缓存池中已经提前存进去了一些元素,提高数据的读取速度。在此之前,先了解一下Java的自动包装机制。

本文参考自CS-Notes中的java基础

拆箱装箱

基本类型要转换成包装类型,需要调用包装类型的静态valueOf()函数;而包装类型要转换成基本类型,需要调用以基本类型开头的Value(),比如 intValue()

在一般情况下,Java会自动帮你实现拆箱装箱,比如

Integer x = 2;     // 装箱   实际是Integer x = Integer.valueOf(2)
int y = x;         // 拆箱   实际是int y = intValue(x)

拆箱装箱详情可参考深入剖析Java中的装箱和拆箱(缓存池技术)


缓存池介绍

在使用这些基本类型对应的包装类型时,如果该数值范围在缓冲池范围内,就可以直接使用缓冲池中的对象。否则,就创建一个对象存储相应的数据。

各种基本类型的缓存池内容如下:

boolean values true and false                //布尔类型中的两个取值  true和false
all byte values                              //byte类型所有数据,即-128~127
short values between -128 and 127            //short类型大小范围-128~127
int values between -128 and 127              //int类型大小范围  -128~127
char in the range \u0000 to \u007F           //char类型所有数据,即所有字符

我们可以看一下Integer缓存池的源码(1.8版本的源码):

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

在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax=<size> 来指定这个缓冲池的大小,该选项在 JVM 初始化的时候会设定一个名为 java.lang.IntegerCache.high 系统属性,然后 IntegerCache 初始化的时候就会读取该系统属性来决定上界。

创建包装类型的对象有两种方式,两种方法都可以将基本类型作为参数传入。两种方法的区别在于:

  • new Integer(123) 每次都会新建一个对象
  • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x == y);    // false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z == k);   // true
Integer m = Integer.valueOf(189);
Integer n = Integer.valueOf(189);
System.out.println(m == n);   // false   189大于缓存池的最大值127 因此每次都会新建一个对象 他们的地址不同 

再看看valueOf()方法的源码:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];     //如果在缓存范围内,直接获取缓存中的地址
        return new Integer(i);                                      //否则新建一个对象
    }

可以发现,他是先判断数值是否在缓存池的范围中,如果在就直接返回缓存池中的对象,如果不存在会直接返回一个 new 出来的新的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值