Integer 的缓存机制

本文深入探讨了Java中Integer的缓存机制,包括装箱和拆箱的过程,以及valueOf方法如何利用缓存来提高效率。揭示了在特定范围内(-128至127)的Integer对象是如何被复用的,从而避免不必要的对象创建。

在了解 Integer 的缓存机制之前,先了解一下装箱和拆箱。
Integer --> int 拆箱 intValue();
int --> Integer 装箱 valueOf();

一、什么时候触发装箱、拆箱?

1.1 装箱

将一个 int 的数值,赋值给一个 Integer 引用会触发装箱过程。如:

Integer a = 10;		//等价于	Integer a = Integer.valueOf(10);

由于10为 int 类型,在赋值给 a 时,会先调用 valueOf() 方法从缓存中取出一个 Integer 对象或者创建一个值为 10 的 Integer 对象(valueOf() 方法后面具体再详述)。

1.2 拆箱

① 将一个 Integer 的包装类型对象赋值给 int 类型的变量,如:

Integer a = 10;			//上面说到,该语句会触发装箱过程,返回一个 Integer 对象
int b = a;				//将 Integer 类型变量赋值给 int 类型变量,会触发拆箱过程
						//等价于 int b = a.intValue();	直接返回一个 int 的值

② 进行运算符运算时

Integer a = 10;
Integer b = 20;
System.out.println(a * b);//触发拆箱过程,等价于	a.intValue() * b.intValue()

注意:当进行 == 运算时,若两个数据类型都为 Integer 时,它们将直接比较这两个 Integer 对象是否一样;若有一个数据类型为 int ,另外一个数据类型为 Integer 时,Integer 的数据将进行拆箱转换为 int,然后再进行比较值是否相等。如:

Integer a = 10;
Integer b = 10;
int c = 10;

System.out.println(a == b);	//等价于 Integer.valueOf(10) == Integer.valueOf(10) ;	true
System.out.println(a == c);	//等价于 a.intValue() == c		true

二、Integer 缓存机制

当在进行装箱操作时,需要装箱的值的大小处于 -128 到 127 时,调用 Integer.valueOf() 方法将会从缓存中直接取出已经预先创建好的 Integer 对象;当数值不处于 【-128,127】区间时,将会直接 new Integer();进行新创建一个对象。

查看 Integer 的 valueOf() 方法的源码:

    public static Integer valueOf(int i) {
    	// IntegerCache.low = -128, IntegerCache.high = 127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
        	// cache 是一个存放着值为 -128 到 127 的 Integer 数组
        	//从缓存数组直接取对应的 Integer 对象
            return IntegerCache.cache[i + (-IntegerCache.low)];
        
        //数值不在 [-128, 127] 区间,直接 new 一个 Integer 对象
        return new Integer(i);
    }

查看 IntegerCache 类源码(Integer 的缓存类):

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        //缓存数组,用来存放 -128 到 127 的 Integer 对象
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.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 = 127
            high = h;

			// 创建一个大小为 256 的 Integer 对象数组
            cache = new Integer[(high - low) + 1];
            // low = -128
            int j = low;
            // 从 -128 开始到 127 结束,每个数值创建一个 Integer 对象,并把该对象放置到 cache 数组中
            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() {}
    }

IntegerCache 类是 Integer 的一个内部类,该类的主要功能是存储 [-128, 127] 范围的 Integer 对象。

验证:

Integer a = 10;
Integer b = 10;
Integer c = 128;
Integer d = 128;

System.out.println(a == b);		//true
System.out.println(c == d)		//false

a == b 的结果为 true 是因为它们都会进行装箱,调用 valueOf() 方法,且大小在 [-128, 127],直接从缓存数组中直接取出,取出的 Integer 对象是同一个对象,所以 a == b 为 true
c == d 的结果为 false,是因为其值不在 [-128, 127] 范围内,会直接 new 一个 Integer 对象(每new 一个对象,它们就会内存的不同位置创建对象)

### Java Integer 缓存机制的内部实现与原理 Java 中的 `Integer` 类是一个不可变的包装类,用于表示整数。为了优化性能,Java 提供了一种特殊的缓存机制来减少小范围整数对象的频繁创建和销毁操作。这种缓存机制通过 `IntegerCache` 实现,其核心在于对特定范围内的整数值进行预加载并复用。 #### 1. 缓存范围 在 Java 中,`IntegerCache` 默认会缓存从 `-128` 到 `127` 的整数对象[^3]。这个范围是 JVM 的默认设置,可以通过修改系统属性 `java.lang.Integer.IntegerCache.high` 来调整上限值,但下限值始终固定为 `-128`。 #### 2. 内部实现 `IntegerCache` 是一个静态内部类,位于 `Integer` 类中。它通过一个数组 `cache` 存储缓存的对象。以下是关键代码片段: ```java private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // 确定缓存的上限值,默认为127 int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // 最大限制为 Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) + 1); } catch (NumberFormatException nfe) { // 忽略非法输入,使用默认值 } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // 确保共享变量初始化完成 assert IntegerCache.high >= 127; } private IntegerCache() {} } ``` 上述代码展示了 `IntegerCache` 的初始化过程。在类加载时,会根据配置生成一个从 `-128` 到 `high` 的整数对象数组,并存储在 `cache` 中[^5]。 #### 3. 自动装箱缓存机制 当通过自动装箱(如 `Integer i = 1;`)或调用 `Integer.valueOf()` 方法创建 `Integer` 对象时,JVM 会检查该值是否在缓存范围内。如果在范围内,则直接返回缓存中的对象;否则,会创建一个新的 `Integer` 对象。 以下是一些示例代码及其行为: ```java Integer a = 100; // 调用 Integer.valueOf(100),返回缓存对象 Integer b = 100; // 调用 Integer.valueOf(100),返回相同的缓存对象 System.out.println(a == b); // true,因为两者指向同一个缓存对象[^4] Integer c = 150; // 调用 Integer.valueOf(150),超出缓存范围,创建新对象 Integer d = 150; // 调用 Integer.valueOf(150),同样创建新对象 System.out.println(c == d); // false,因为两者指向不同的对象 Integer e = new Integer(100); // 使用构造器显式创建新对象 Integer f = 100; // 调用 Integer.valueOf(100),返回缓存对象 System.out.println(e == f); // false,因为一个是新对象,另一个是缓存对象[^2] ``` #### 4. 性能优化机制 通过 `IntegerCache` 缓存机制,Java 避免了频繁创建和销毁小范围整数对象,从而减少了内存分配和垃圾回收的压力。这种优化对于频繁使用的整数值尤其有效,例如循环计数器、索引等。 #### 5. 注意事项 - 使用 `==` 比较两个 `Integer` 对象时,比较的是它们的引用地址,而非实际值。因此,在比较整数值时应优先使用 `equals()` 方法。 - 如果需要比较原始类型 `int` 和 `Integer` 对象,可以直接使用 `==`,因为 `Integer` 会被自动拆箱为 `int` 进行比较。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值