使用 new 运算符在 Java 中进行整数缓存

Integer caching in Java with new operator

在下面的 class 中,我尝试将包装器 class 与原语进行比较,但结果不同。

我检查了以下 links links:

The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.

如果有一个新对象,那么 ac 怎么相等?

如果b等于cc等于a,那么a应该等于b。但在以下情况下,我得到了 a != c.

请说明。

class WrapperCompare {

    public static void main (String args[]) {
        Integer a = new Integer(10);    
        Integer b = 10; 
        int c=10;
        System.out.println(b==c);       //true
        System.out.println(a==b);       //false
        System.out.println(a==c);       //true
    }
}

更新: 通过参考这个linkInteger caching

Basically, the Integer class keeps a cache of Integer instances in the range of -128 to 127, and all autoboxing, literals and uses of Integer.valueOf() will return instances from that cache for the range it covers.

所以在这种情况下,所有陈述都应该是正确的。

说明

当您将 Integerint== 进行比较时,它需要将 Integer 转换为 int。这叫做拆箱

JLS§5.1.8:

If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()

此时,您正在比较 intint。基元没有实例的概念,它们都引用相同的值。因此,结果是 true.

所以你的实际代码是

a.intValue() == c

导致比较 10 == 10,两个 int 值,不再有 Integer 个实例。

当您比较 IntegerInteger 时,您可以看到 new Integer(...) 确实创建了新实例。你在 a == b.

中做到了

备注

构造函数 new Integer(...) 弃用 。您应该改为使用 Integer#valueOf,它可能更快并且还使用内部缓存。来自 documentation:

Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.

缓存在这里很重要,因为它会导致 == 再次为真(对于缓存值):

Integer first = Integer.valueOf(10);
Integer second = Integer.valueOf(10);
System.out.println(first == second); // true

保证缓存 -128+127 之间的值,但也可用于其他值。

另请注意,您的 b 实际上是从缓存中取出的,因为

Integer b = 10;
// same as
Integer b = Integer.valueOf(10);
// and not
Integer b = new Integer(10);

因此 boxing 通过 Integers 缓存(参见 JLS§5.1.7)。