深入理解 Java 中的 Integer 缓存机制

在 Java 中,Integer 类型的对象比较有一些特殊的规则。特别是当我们使用自动装箱(autoboxing)时,Java 会在一定范围内缓存这些对象,以提高性能和减少内存使用。

自动装箱与拆箱

在 Java 5 之后,引入了自动装箱(autoboxing)和自动拆箱(unboxing)的概念。自动装箱是指将基本数据类型自动转换为对应的包装类对象,而自动拆箱则是将包装类对象自动转换为基本数据类型。

例如:

java 复制代码
Integer integer1 = 126; // 自动装箱
int int1 = integer1;    // 自动拆箱

Integer 缓存机制

为了提高性能和减少内存使用,Java 对 Integer 对象在一定范围内进行了缓存。这个范围通常是 -128 到 127。也就是说,当我们创建一个值在这个范围内的 Integer 对象时,Java 会返回一个缓存的实例,而不是创建一个新的对象。

示例代码

让我们通过一个简单的示例代码来说明这一点:

java 复制代码
public class Main {
    public static void main(String[] args) {
        Integer integer1 = 126;
        Integer integer2 = 126;
        System.out.println(integer1 == integer2); // 输出 true

        Integer integer3 = 128;
        Integer integer4 = 128;
        System.out.println(integer3 == integer4); // 输出 false
    }
}

在上面的代码中,我们创建了两个 Integer 对象 integer1integer2,它们的值都是 126。由于 126 在 -128 到 127 的缓存范围内,Java 会使用缓存的 Integer 对象。因此,integer1integer2 实际上引用的是同一个对象,所以 integer1 == integer2 会返回 true

然而,对于 integer3integer4,它们的值是 128,不在缓存范围内。因此,Java 会创建两个不同的 Integer 对象,所以 integer3 == integer4 会返回 false

Integer 缓存的实现

Integer 缓存机制的实现可以在 Integer 类的源码中找到。以下是相关的代码片段:

java 复制代码
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

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 =
            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;

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

valueOf 方法中,如果传入的整数值在缓存范围内,Java 会返回缓存的 Integer 对象,否则会创建一个新的 Integer 对象。

使用 equals 方法进行比较

在实际开发中,通常建议使用 equals 方法来比较两个 Integer 对象的值,而不是使用 == 运算符。equals 方法会比较对象的值,而 == 运算符比较的是对象的引用。

java 复制代码
public class Main {
    public static void main(String[] args) {
        Integer integer1 = 128;
        Integer integer2 = 128;
        System.out.println(integer1.equals(integer2)); // 输出 true
    }
}

在这个示例中,integer1integer2 的值都是 128,虽然它们是不同的对象,但 equals 方法会返回 true,因为它们的值相等。

其他包装类的缓存机制

除了 Integer 之外,其他一些包装类(如 ByteShortLongCharacter)也有类似的缓存机制。例如:

  • Byte 缓存范围是 -128 到 127。
  • Short 缓存范围是 -128 到 127。
  • Long 缓存范围是 -128 到 127。
  • Character 缓存范围是 0 到 127。

这些缓存机制的实现与 Integer 类似,都是为了提高性能和减少内存使用。

结论

Java 中 Integer 缓存机制在一定范围内缓存了 Integer 对象,以提高性能和减少内存使用。理解这一机制对于编写高效的 Java 代码非常重要,特别是在需要频繁使用 Integer 对象的场景中。

相关推荐
要加油哦~2 分钟前
vue · 插槽 | $slots:访问所有命名插槽内容 | 插槽的使用:子组件和父组件如何书写?
java·前端·javascript
crud5 分钟前
Spring Boot 3 整合 Swagger:打造现代化 API 文档系统(附完整代码 + 高级配置 + 最佳实践)
java·spring boot·swagger
天天摸鱼的java工程师10 分钟前
从被测试小姐姐追着怼到运维小哥点赞:我在项目管理系统的 MySQL 优化实战
java·后端·mysql
周某某~22 分钟前
四.抽象工厂模式
java·设计模式·抽象工厂模式
异常君1 小时前
高并发数据写入场景下 MySQL 的性能瓶颈与替代方案
java·mysql·性能优化
烙印6011 小时前
MyBatis原理剖析(二)
java·数据库·mybatis
你是狒狒吗1 小时前
TM中,return new TransactionManagerImpl(raf, fc);为什么返回是new了一个新的实例
java·开发语言·数据库
勤奋的知更鸟1 小时前
Java编程之组合模式
java·开发语言·设计模式·组合模式
千|寻1 小时前
【画江湖】langchain4j - Java1.8下spring boot集成ollama调用本地大模型之问道系列(第一问)
java·spring boot·后端·langchain
爱编程的喵1 小时前
深入理解JavaScript原型机制:从Java到JS的面向对象编程之路
java·前端·javascript