183

从 Java 1.5 开始,您几乎可以在许多情况下Integer与之互换。int

然而,我发现我的代码中有一个潜在的缺陷,这让我有点吃惊。

以下代码:

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 上的本地主机上看到了这种行为。在这种特殊情况下,代码成功通过了大约 20 次比较,但在 2 次比较失败。该问题始终可以重现。

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

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

除了下面所有的好答案之外,下面的 stackoverflow 链接还有很多额外的信息。它实际上会回答我原来的问题,但是因为我没有在我的问题中提到自动装箱,所以它没有出现在选定的建议中:

为什么编译器/JVM 不能让自动装箱“正常工作”?

4

7 回答 7

286

JVM 正在缓存整数值。因此,与的比较==仅适用于 -128 和 127 之间的数字。

参考:#Immutable_Objects_.2F_Wrapper_Class_Caching

于 2010-09-03T17:08:53.733 回答
86

您不能将两者Integer与简单==的对象进行比较,因此大多数时候引用不会相同。

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

如果被装箱的值 p 是真、假、一个字节、一个 \u0000 到 \u007f 范围内的字符,或者一个介于 -128 和 127 之间的 int 或短数字,则令 r1 和 r2 为任意两次装箱转换的结果p。r1 == r2 总是如此。


资源 :

在同一主题上:

于 2010-09-03T17:10:26.727 回答
5

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

于 2010-09-03T17:06:04.990 回答
5

Integer指的是引用,也就是说,当比较引用时,您要比较的是它们是否指向同一个对象,而不是值。因此,您看到的问题。它适用于普通int类型的原因是它取消了Integer.

我可以补充一点,如果你正在做你正在做的事情,为什么要以if声明开头?

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );
于 2010-09-03T17:07:08.823 回答
5

“==”总是比较值的内存位置或对象引用。equals 方法总是比较值。但 equals 也间接使用“==”运算符来比较值。

Integer 使用 Integer 缓存来存储从 -128 到 +127 的值。如果 == 运算符用于检查 -128 到 127 之间的任何值,则返回 true。对于这些值以外的值,它返回 false 。

请参阅链接以获取更多信息

于 2016-07-28T06:13:04.963 回答
3

除了这些给出的很好的答案之外,我学到的是:

切勿将对象与 == 进行比较,除非您打算通过它们的引用来比较它们。

于 2020-04-16T01:57:25.553 回答
2

以及为了使用的正确性,==您可以Integer在进行比较之前将比较值之一拆箱==,例如:

if ( firstInteger.intValue() == secondInteger ) {..

第二个将被自动拆箱(当然你必须先检查nulls )。

于 2020-05-13T09:20:45.297 回答