Loading...

从源码看java Integer缓存机制

2025-12-30
0
-
- 分钟
|

从源码看java Integer缓存机制

看以下代码:

public class SimpleTest {
    public static void main(String[] args) {
        // 情况一
        Integer a = 127;
        Integer b = 127;
        System.out.println("127 使用 == 比较: " + (a == b));

        // 情况二
        Integer c = 128;
        Integer d = 128;
        System.out.println("128 使用 == 比较: " + (c == d));
    }
}

== 在Java中比较的是地址值而不是数据大小,而Integer又是java包装类,所以有人可能认为情况一的结果也是 false。

毕竟,a 和 b 看起来是两个独立声明的对象,直接用 == 比较引用理应是不相等的。但实际运行结果却是:

true

false

这看似矛盾的结果,其实正是Java为了优化性能而设计的“Integer缓存机制”在起作用。

这背后的玄机在于 Integer 的自动装箱(Autoboxing)机制。当我们执行 Integer a = 127; 时,编译器实际上执行的是 Integer.valueOf(127)。

我们来看 Integer.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 一个新对象。

为什么 127 是 true,128 是 false?

  1. 127 的情况:

Java 在启动时,IntegerCache 类会默认预先创建好 -128 到 127 之间所有整数的 Integer 对象,并放入缓存池中。

当执行 Integer a = 127; 和 Integer b = 127; 时,它们获取的都是缓存池中同一个对象的引用。因此,a == b 比较的是同一个内存地址,结果自然为 true。 2. 128 的情况:

由于 128 超出了默认缓存范围(127是上限),Integer c = 128; 和 Integer d = 128; 会分别执行 new Integer(128),在堆内存中创建了两个不同的新对象。虽然它们的值相同,但 == 比较的是地址,两个对象的地址不同,所以结果为 false。

总结与建议

这个现象被称为Java中的“128陷阱”。为了避免在开发中踩坑,请务必记住:

在比较两个包装类(如 Integer)的值时,永远使用 .equals() 方法,而不是 ==。

== 只能用于判断基本数据类型(如 int)的值是否相等,或者判断两个对象是否为同一个引用;而 .equals() 才是用来判断两个对象的内容是否相等的标准方法。

文章目录