过载等于值得吗
请考虑以下代码段:
import java.util.*;
public class EqualsOverload {
public static void main(String[] args) {
class Thing {
final int x;
Thing(int x) { this.x = x; }
public int hashCode() { return x; }
public boolean equals(Thing other) { return this.x == other.x; }
}
List<Thing> myThings = Arrays.asList(new Thing(42));
System.out.println(myThings.contains(new Thing(42))); // prints "false"
}
}
请注意,返回!!!我们似乎失去了我们的东西!contains
false
当然,bug 是因为我们意外地重载了 Object.equals(Object)
而不是被覆盖。如果我们按如下方式编写,则按预期返回。class Thing
contains
true
class Thing {
final int x;
Thing(int x) { this.x = x; }
public int hashCode() { return x; }
@Override public boolean equals(Object o) {
return (o instanceof Thing) && (this.x == ((Thing) o).x);
}
}
有效的 Java 第 2 版,第 36 项:始终如一地使用 Override 注释,使用本质上相同的参数来建议应一致地使用。当然,这个建议是好的,因为如果我们试图在第一个片段中声明,我们友好的小编译器会立即指出我们愚蠢的小错误,因为它是一个重载,而不是一个覆盖。@Override
@Override equals(Thing other)
然而,这本书没有特别介绍的是,重载是否是一个好主意。基本上,有3种情况:equals
- 只有过载,没有覆盖 - 几乎肯定是错误的!
- 这基本上是上面的第一个片段
- 仅覆盖(无过载) - 修复的一种方法
- 这基本上是上面的第二个片段
- 重载和覆盖组合 - 另一种修复方法
第三种情况由以下代码段说明:
class Thing {
final int x;
Thing(int x) { this.x = x; }
public int hashCode() { return x; }
public boolean equals(Thing other) { return this.x == other.x; }
@Override public boolean equals(Object o) {
return (o instanceof Thing) && (this.equals((Thing) o));
}
}
在这里,即使我们现在有2个方法,仍然有一个相等逻辑,它位于重载中。简单地委托重载。equals
@Override
所以问题是:
- “仅覆盖”与“过载和覆盖组合”的优缺点是什么?
- 重载是否有正当理由,或者这几乎肯定是一种不好的做法?
equals