正确实现等于

时间:2012-05-03 07:37:42

标签: java equals

我已经读过,在实现equals时考虑别名是个坏主意 equals的示例为File 我想知道为什么这是个坏主意?仅仅因为实施更难以正确吗? 如果FileAFileB引用同一个文件但路径名不同,为什么它们不相等?

3 个答案:

答案 0 :(得分:2)

我认为File实际上是一个非常棘手的例子。

可以期望Java运行时知道hard links吗?挂载的NFS共享上的硬链接?

我认为“不”是对最后一个问题的公平答案,在这种情况下File.equals()只能在尽力而为的基础上发挥作用。

答案 1 :(得分:2)

对于指向同一实际文件的别名文件名,使equals()返回true是一个坏主意,因为违反了关于相等行为的常见假设

请考虑以下示例:

  • 即使他们现在引用相同的基础文件,也可能在将来发生变化(例如,由于文件系统的变化导致一条路径无效)。你现在想要的东西在未来保持平等(除非你明确地改变它们)。
  • 如果您转换文件(例如,通过上一个目录),那么结果也将不相等。这里违反的假设是你希望同样的操作应用于两个相同的事情以产生相同的结果。

因此我们可以看到,考虑别名会对两个所谓的“相等”对象产生一些意想不到的行为。当人们做出不正确的假设时,这可能会在将来引起奇怪和微妙的错误。

次要但也是相关的问题是考虑到别名可能会增加相当大的实现复杂性和性能开销。您通常希望equals()非常高效,因为它可能经常被调用:如果它被迫对操作系统进行IO调用以确定文件别名,那么情况就不太可能如此。

在这种情况下,我将实现一个完全不同的函数,该函数测试指向同一物理文件 - refersToSameFile或类似的东西。这允许您为操作使用更具描述性的名称,并避免混淆对相等行为的期望。

答案 2 :(得分:1)

确切地说,为什么他们不平等?或者他们为什么会这样?

这只是品味和/或要求的问题。在某些情况下,您需要在两个别名之间进行多样化,在其他情况下,只有目标文件才重要。决定并不是那么容易,因此决定至少确保java版本之间的兼容性。

此外,在某些文件系统上,无法检测您是在处理链接还是实际文件(至少不使用默认的jre工具)。