Java学习第一百五十五部分——Integer缓存机制

目录

一、前言简介

二、详细说明

三、对比总结


一、前言简介

       本文介绍Java 中 `Integer` 类的一个核心特性——整数缓存机制(Integer Cache)。Java 的 Integer 类通过静态缓存池,默认预先创建并复用了数值在 -128 到 127 之间的对象,以提高空间和时间效率。

二、详细说明

1. 示例代码与解析

无需多言,直接上代码。

Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true

Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false
  • `a == b` 为 `true`:因为 `127` 在默认的缓存范围 `-128~127` 之内。当你使用 `Integer a = 127;` 这种写法时,Java 会自动调用 `Integer.valueOf(127)` 来获取对象。`valueOf()` 方法会优先从缓存池(cache)中返回一个已经存在的、值相同的 `Integer` 对象。因此,`a` 和 `b` 指向的是同一个对象,`==` 比较的是引用地址,所以结果为 `true`。

  • `c == d` 为 `false`:因为 `128` 超出了默认的缓存范围。`Integer.valueOf(128)` 在缓存池中找不到对应的对象,于是会在堆内存中创建一个新的 `Integer` 对象。因此,`c` 和 `d` 指向的是两个不同的、但值相同的对象。`==` 比较它们的引用地址,自然不相等,返回 `false`。

2. `Integer.valueOf()` vs `new Integer()`

这是理解这个问题的关键。

`Integer.valueOf(int i)`:这是一个静态工厂方法。它的核心逻辑就是使用缓存

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i); // 只有不在缓存范围内,才 new 新对象
    }

所以,`valueOf()` 不一定创建新对象。

`new Integer(int i)`:这是一个构造函数调用。它永远会在堆上创建一个全新的对象,完全无视缓存范围

    Integer e = new Integer(127);
    Integer f = new Integer(127);
    System.out.println(e == f); // false,因为是两个不同的对象
    System.out.println(e.equals(f)); // true,因为值相等

3. 自动装箱(Autoboxing)

Java 5 引入了自动装箱/拆箱机制。当我们写 `Integer a = 127;` 时,编译器会自动将其转换为 `Integer a = Integer.valueOf(127);`。

所以,`Integer a = 127;` 在底层完全等价于 `Integer a = Integer.valueOf(127);`。这就是为什么它会受到缓存机制的影响。

4. `==` 和 `equals()` 的区别

这是问题的另一个核心。

`==` 操作符:对于对象类型,它比较的是两个变量指向的内存地址是否相同(即是否是同一个对象)。它不关心对象内部的值。
`equals()` 方法:这个方法由类自己实现,用于比较两个对象的逻辑内容是否相等。`Integer` 类重写了 `equals()` 方法,使其比较的是包装的 `int` 值。

正确比较两个 `Integer` 对象值的方法永远是使用 `equals()`

Integer c = 128;
Integer d = 128;
System.out.println(c == d);       // false(比较地址,不推荐)
System.out.println(c.equals(d));  // true(比较值,正确!)

5. 缓存范围的调整

缓存的上限 `127` 是默认值,但并非不可改变。缓存的上限是通过 JVM 的启动参数来设置的。

  • `-XX:AutoBoxCacheMax=<size>`:你可以通过这个 JVM 参数来调整 `Integer` 缓存的最大值。

  • 例如,使用 `java -XX:AutoBoxCacheMax=500 YourApp` 启动程序,那么缓存范围就会变成 `-128~500`。

  • 注意:这个参数只调整上限(high),下限(low)始终是 -128。

  • 这个参数对其他整型包装类(如 `Long`, `Short`)的缓存没有影响。

6. 其他包装类的缓存

不仅 `Integer`,其他包装类也有缓存机制:

  • `Byte`:全部缓存(-128~127,一共256个值)。因为 byte 的范围就是这么多。

  • `Short`:缓存 -128~127。

  • `Long`:缓存 -128~127。

  • `Character`:缓存 0~127(ASCII/Unicode 字符)。

  • `Boolean`:缓存 `TRUE` 和 `FALSE` 两个实例(全部缓存)。

  • `Float` 和 `Double`:没有缓存。`valueOf` 方法总是返回新对象。

三、对比总结

操作是否使用缓存说明
Integer a = 100; (自动装箱)底层调用 Integer.valueOf(100)
Integer.valueOf(100)是 (如果在范围内)优先从缓存返回对象
new Integer(100)始终创建新对象
== 比较-比较对象地址,结果不可预测,不要用于值比较
equals() 比较-比较包装的值,是正确比较内容的方法
  • 永远使用 `equals()` 来比较两个包装类对象的值。

  • 理解 `==` 在对象比较时的行为,避免踩坑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值