我们正在使用Sonar检查代码的质量,Sonar找到了比较对象的代码,如下所示:
if (cellOfInterest == currentCell) { … }
Sonar发现这种特殊的身份检查足以将其称为关键,并建议用相同的检查替换身份检查(使用==
)(改为使用.equals()
)。身份检查,因此背后的基本原理通常不是那个意思。
然而,在我们的例子中,我们遍历Cell
的列表并检查每次迭代(currentCell
)是否正在处理我们已经拥有的特殊单元格(cellOfInterest
)
我想知道是否有其他模式比我们的模式更常见,并且只是通过使用不同的设计来避免这个问题。或者您建议在上述情况下避免使用身份检查?
我们考虑用如上所述的等式检查替换身份检查,但它似乎不适用于我们的情况,因为其他单元格可能“相等”但不相同。
欢迎所有想法!
答案 0 :(得分:7)
如果您需要身份,那么这就是您所需要的。警告是有道理的,因为它通常是一个错误,但在这种情况下它不是。
作为一个例子,IdentityHashMap(使用身份与平等相关)在其javadoc中有这个:
这个类不是通用的Map实现! [...] 此类仅适用于需要引用相等语义的极少数情况。
所以它很少有用但有其用途。你处于类似的位置。当然,its internal code完全符合您的预期,它使用==
来获取密钥。
结论:我不明白为什么你需要让代码更复杂只是因为一些静态代码分析工具说它可能是一个问题 - 这样的工具应该可以帮助你,而不是强迫你进入某些奇怪的构造,基本上会做同样的事情。我会解释为什么==
在评论中用于清晰,将其标记为误报并继续前进。
如果您确实要删除警告,我能想到的唯一选择是使用equals
并将equals
方法更改为:
Object#equals
答案 1 :(得分:2)
对于Strings和大多数其他Java对象,可能有2个实例,这些实例的身份不相等但实际上等同于.equals
。通常避免==
进行比较(使用equals或compareTo代替)但是如果它有效,它就可以工作。您可以在SonarQube中将该项目标记为误报。
答案 2 :(得分:1)
如果你只是用等号调用替换你的身份检查,你将不会遇到问题(除了你必须检查cellOfInterest上的空值),因为在Object中的equals的默认实现是身份检查。
if (cellOfInterest != null && cellOfInterest.equals(currentCell)) { … }
不会破坏代码。它的行为与您的代码完全相同,当我可能认为currentCell不会为空时。
要省略空检查(并保留两个值为null的行为),您也可以使用(自Java 7开始)
if(Objects.equals(cellOfInterest, currentCell)) { ...}
一般来说,使用equals是更好的架构。
要查看您提及的两种情况:
如果自己可以改变课程,你可能(或可能不会)得出结论:平等有比平等更好的方法;所以你只需要改变你班上的等号(并且不要忘记hashCode!)。
如果您无法更改类,则必须信任该类提供程序对equals和hashCode的有意义实现。