为什么在 Java 中比较整数包装器时,128==128 是假的,但 127==127 是真的?

class D {
    public static void main(String args[]) {
        Integer b2=128;
        Integer b3=128;
        System.out.println(b2==b3);
    }
}

输出:

false

class D {
    public static void main(String args[]) {
        Integer b2=127;
        Integer b3=127;
        System.out.println(b2==b3);
    }
}

输出:

true

注意:-128 和 127 之间的数字为真。


答案 1

当您在Java中编译一个数字文本并将其分配给整数(大写)时,编译器会发出:I

Integer b2 =Integer.valueOf(127)

使用自动装箱时也会生成此行代码。

valueOf实现为使某些数字“池化”,并且对于小于 128 的值,它将返回相同的实例。

来自 java 1.6 源代码,第 621 行:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

的值可以配置为另一个值,具有系统属性。high

-Djava.lang.Integer.IntegerCache.high=999

如果使用该系统属性运行程序,它将输出 true!

显而易见的结论是:永远不要依赖两个相同的引用,始终将它们与方法进行比较。.equals()

因此,对于 b2,b3 的所有逻辑相等值,将打印 true。b2.equals(b3)

请注意,缓存不是出于性能原因,而是为了符合JLS,第5.1.7节;必须为值 -128 到 127(包括 -128 和 127)指定对象标识。Integer

Integer#valueOf(int) 也记录了以下行为:

此方法可能会通过缓存经常请求的值来显著提高空间和时间性能。此方法将始终缓存 -128 到 127(包括 -128 到 127)范围内的值,并可能缓存此范围之外的其他值。


答案 2

自动装箱缓存 -128 到 127。这在 JLS (5.1.7) 中指定。

如果被装箱的值 p 是 true、false、一个字节、一个介于 \u0000 到 \u007f 范围内的 char,或者是一个介于 -128 和 127 之间的整数或短数字,则让 r1 和 r2 成为 p 的任意两个装箱转换的结果。总是 r1 == r2。

处理对象时要记住的一个简单规则是 - 如果要检查两个对象是否“相等”,请使用,当您要查看它们是否指向同一实例时使用。.equals==


推荐