Java:整数等于==

Jer*_*ell 142 java primitive integer wrapper equals-operator

从Java 1.5中,你几乎可以互换Integer使用int在许多情况下.

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

以下代码:

Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
    mismatch = true;
Run Code Online (Sandbox Code Playgroud)

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

将条件更改为:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))
Run Code Online (Sandbox Code Playgroud)

解决了这个问题.

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

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

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

除了下面的所有精细答案之外,以下stackoverflow链接还有相当多的附加信息.它实际上已经回答了我原来的问题,但因为我没有在我的问题中提到自动装箱,所以它没有出现在选定的建议中:

为什么编译器/ JVM不能让autoboxing"正常工作"?

Ada*_*dam 225

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

  • @Jeremy是的,这是一个相当模糊的问题,但作为一般规则,你使用.equals()表示对象,==表示原语.您不能依靠自动装箱进行相等测试. (2认同)
  • 请注意, new Integer(1) != new Integer(1) 也是如此。new 总是返回一个新地址。自动装箱使用缓存版本。其他返回整数(不更新它们)的方法也可能返回缓存的值。 (2认同)

Col*_*ert 72

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

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

如果被装箱的值p为true,false,一个字节,范围为\ u0000到\ u007f的char,或者介于-128和127之间的int或短号,则让r1和r2为任意两个装箱转换的结果p.始终是r1 == r2的情况.


资源:

在同一主题上:

  • 回复:保证。我还是不会太依赖它。`new Integer(1) == new Integer(1)` 仍然是 false。 (2认同)
  • @Thilo `new ... == new ...` 始终是 `false`。 (2认同)
  • @Thilo True,在处理对象时总是使用`equals()`.这应该是学习Java时应该知道的第一件事.顺便说一下,我猜想`Integer`的构造函数是私有的,即实例总是通过`valueOf()`方法创建的.但我发现构造函数是公开的. (2认同)

vij*_*jay 6

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

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

请参阅链接以获取一些附加信息


Mat*_*ttC 5

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


whe*_*ies 5

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

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

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );
Run Code Online (Sandbox Code Playgroud)