Integer的缓存机制

Integer的自动装箱和自动拆箱

装箱:基本类型 --> 包装类/引用类型
Integer i1=100; 在编译后,class文件中自动加上了valueOf方法
拆箱:包装类/引用类型 --> 基本类型
int i2 = i1; 在编译后,class文件中自动加上了intValue方法
注意:自动装箱和自动拆箱只发生在编译阶段。
在这里插入图片描述

Integer.valueOf方法

public static Integer valueOf(int i) {
    //判断是否在Integer内部的缓存数组中,如果存在则直接返回缓存数组中的对象
    //IntegerCache是Integer的内部类
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        //根据索引获取缓存中的Integer
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

IntegerCache类

private static class IntegerCache {
    static final int low = -128;  //缓存池中最小值,-128
    static final int high;        //缓存中最大值,默认为127
    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);
                // 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;
		//开辟大小为(high - low) + 1的Integer数组
        cache = new Integer[(high - low) + 1];
        int j = low;
        //IntegerCache类初始化的时候就对内部的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() {}
}

注:数组赋值的另外写法
int ii[];
ii = new int[5];
System.out.println(Arrays.toString(ii));  //[0, 0, 0, 0, 0]

代码示例

Integer i1 = 100;
Integer i2 = 100;
System.out.println(i1==i2); //true  因为取出来的都是缓存池中的Integer对象,所以对象地址相同
Integer i3 = 1000;
Integer i4 = 1000;
System.out.println(i3==i4);  //false   超出了缓存池,新创建对象
System.out.println(i3.equals(i4));  //true  比较值,相等

结论

创建Integer的时候,以下两种方法:
方法1:Integer n = new Integer(100); //总是创建新的对象
方法2:Integer n = Integer.valueOf(100); //静态工厂方法,尽可能地返回缓存的实例以节省内存
所以,为了节省内存,Integer.valueOf()对于较小的数,始终返回相同的实例,因此,有时候使用 == 比较“恰好”为true,但我们绝不能因为Java标准库的Integer内部有缓存优化就用 == 比较,必须用equals()方法比较两个Integer

### 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、付费专栏及课程。

余额充值