问题

从Java 1.5开始,在很多情况下你几乎可以互换Integerint

但是,我在代码中发现了一个潜在的缺陷让我感到有些惊讶。

以下代码:

Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
    mismatch = true;

当值相等时,似乎错误地设置了不匹配,尽管我无法确定在什么情况下。我在Eclipse中设置了一个断点,看到了Integer值都是137,我检查了布尔表达式并且它说它是假的,但当我跨过它时,它设置不匹配为真。

将条件更改为:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))

解决了这个问题。

任何人都能解释为什么会这样吗?到目前为止,我只在自己的PC上看到了我的localhost上的行为。在这种特殊情况下,代码成功地通过了大约20次比较,但在2次失败。问题始终可以重现。

如果这是一个普遍的问题,它应该导致我们的其他环境(开发和测试)出错,但到目前为止,没有人在执行此代码片段的数百次测试后报告该问题。

使用==来比较两个Integer值仍然是不合法的吗?

除了下面的所有精细答案之外,以下stackoverflow链接还有相当多的附加信息。它实际上已经回答了我原来的问题,但因为我没有在我的问题中提到自动装箱,所以它没有出现在所选的建议中:
Why can't the compiler/JVM just make autoboxing "just work"?


#1 热门回答(188 赞)

JVM正在缓存Integer值。 ==仅适用于介于-128和127http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching之间的数字


#2 热门回答(66 赞)

你无法将两个Integer与一个简单的对象进行比较,因此大部分时间参考都不一样。

有一个技巧,在-128和127之间有887246870,引用将与使用3380808267缓存小整数的自动装箱相同。

如果装箱的值为真,false,一个字节,范围为\ u0000到\ u007f的字符,或者介于-128和127之间的int或短号,则让r1和r2为任意两个装箱的结果p的转换始终是r1 == r2的情况。
资源:- JLS - 拳击
关于同一主题:- autoboxing vs manual boxing java


#3 热门回答(5 赞)

问题是你的两个Integer对象就是那个对象。它们不匹配,因为你正在比较两个对象引用,而不是其中的值。显然,重写.equals被覆盖以提供值比较而不是对象引用比较。


原文链接