Java中使用new运算符的整数缓存

23
在下面的类中,我尝试将包装类与原始类型进行比较,但结果不同。
我已经检查了以下链接links:
更有趣的问题是为什么需要new Object();每次创建一个唯一的实例?即为什么new Object();不能缓存?答案是wait(...)notify(...)调用。缓存新的Object()会导致线程在不应该同步时错误地与彼此同步。
如果有一个新对象,那么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
    }
}

更新: 参考此链接整数缓存
基本上,Integer类在范围-128到127之间保留了一个Integer实例的缓存,所有自动装箱、字面量和Integer.valueOf()的使用都将返回该缓存中覆盖范围的实例。
因此,在这种情况下,所有语句都应该是真实的。

2
请注意,构造函数已被弃用,不应再使用。请改用valueOf - Zabuzard
5
除了 a==b 外,这里的表达式都不是在比较对象。 - Andy Turner
5
@Zabuza 错了,new 关键字总是返回一个新的实例。只有通过 valueOf(无论是隐式还是显式调用)才会获取缓存的实例。 - Andy Turner
3
语句 Integer b = 10; 等价于 Integer b = Integer.valueOf(10);(并不是 Integer b = new Integer(10);)。 - Maurice Perry
1
好问题,好答案,好评论。大家干得好! :) - JollyJoker
1个回答

27

解释

当你使用 == 比较 Integerint 时,需要将 Integer 转换为 int,这被称为拆箱

请参阅JLS§5.1.8

如果 r 是类型为 Integer 的引用,则拆箱转换r 转换为 r.intValue()

此时,你正在比较 intint。原始类型没有实例的概念,它们都指向同一个值。因此,结果是 true

所以你实际上的代码是

a.intValue() == c

10 == 10 进行比较,都是 int 类型的值,不再使用 Integer 实例。

当您比较 IntegerInteger 时,您会发现 new Integer(...) 确实创建了新的实例。您在 a == b 中进行了比较。


注意

new Integer(...) 构造函数已经弃用。应该使用 Integer#valueOf,它可能更快,而且使用一个内部缓存。从文档中可以看到:

返回表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则通常应优先使用此方法而不是构造函数 Integer(int),因为这个方法通过缓存经常请求的值来提高空间和时间性能,并且可能缓存范围在 -128127(含)之内的其他值。

这里需要注意缓存,因为它会导致 == 再次为真(对于缓存的值):

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 通过 Integer 的缓存进行(请参见 JLS§5.1.7)。


2
“it is much faster” 是一个过于强烈的说法。正如文档所述,“这种方法很可能会产生明显更好的空间和时间性能”,换句话说,它可以实现潜在的优化,但是否存在取决于具体实现。 - Holger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接