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

2022-09-01 23:26:00

在下面的类中,我试图将包装器类与基元进行比较,但结果是不同的。

我已经检查了以下链接链接

更有趣的问题是,为什么每次都需要创建一个唯一的实例?即为什么不允许缓存?答案是和呼叫。缓存新的 s 会错误地导致线程彼此同步,而它们不应该同步。new Object();new Object();wait(...)notify(...)Object()

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

如果 等于 和 等于 ,则应等于 。但是在以下情况下,我得到了.bccaaba != 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 类将 Integer 实例的缓存保存在 -128 到 127 的范围内,并且所有自动装箱、文本和 Integer.valueOf() 的使用都将从该缓存中返回其覆盖范围的实例。

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


答案 1

解释

当您与 进行比较时,它需要将 转换为 .这称为取消装箱Integerint==Integerint

参见 JLS§5.1.8

如果 是 类型的引用,则取消装箱转换将转换为rIntegerrr.intValue()

此时,您正在比较与 .而原语没有实例的概念,它们都引用相同的值。因此,结果是 。intinttrue

所以你拥有的实际代码是

a.intValue() == c

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

您可以看到,当您与 进行比较时,它确实会创建新实例。您在 .new Integer(...)IntegerIntegera == b


注意

该构造函数已弃用。您应该改用 ,它可能更快,并且还使用内部缓存。从文档中new Integer(...)Integer#valueOf

返回表示指定值的实例。如果不需要新的 Integer 实例,则通常应优先使用此方法而不是构造函数,因为此方法可能通过缓存频繁请求的值来显著提高空间和时间性能。此方法将始终缓存范围为 (包括) 中的值,并可能缓存此范围之外的其他值IntegerintInteger(int)-128127

此处需要注意缓存,因为它再次屈服于 true(对于缓存值):==

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);

所以拳击会通过缓存(参见JLS§5.1.7)。Integer


答案 2

推荐