【发布时间】:2015-09-09 00:07:48
【问题描述】:
J。 Bloch 在其有效的 Java 中为 equals 方法的实现提供了几个规则。他们在这里:
• 自反:对于任何非空引用值 x,x.equals(x) 必须 返回真。
• 对称:对于任何非空引用值 x 和 y, x.equals(y) 必须返回 true 当且仅当 y.equals(x) 返回 true。
• 传递:对于任何非空引用值 x、y、z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,然后 x.equals(z) 必须返回 true。
• 一致:对于任何非空引用 值 x 和 y,x.equals(y) 的多次调用一致 如果未使用任何信息,则返回 true 或始终返回 false in equals 对对象的比较进行了修改。
• 对于任何非空 参考值 x, x.equals(null) 必须返回 false。
但后来他在书中提到了所谓的里氏替换原则:
Liskov 替换原则说,任何重要的属性 一个类型也应该适用于它的子类型,这样任何编写的方法 因为该类型应该同样适用于其子类型
我看不出它与equals 合同有何联系。在编写 equals 实现时,我们真的应该遵守它吗?
问题是关于实现子类的方法。这是书中的例子:
private static final Set<Point> unitCircle;
static {
unitCircle = new HashSet<Point>();
unitCircle.add(new Point(1, 0));
unitCircle.add(new Point(0, 1));
unitCircle.add(new Point(-1, 0));
unitCircle.add(new Point(0, -1));
}
public static boolean onUnitCircle(Point p) {
return unitCircle.contains(p);
}
public class CounterPoint extends Point {
private static final AtomicInteger counter = new AtomicInteger();
public CounterPoint(int x, int y) {
super(x, y);
counter.incrementAndGet();
}
public int numberCreated() { return counter.get(); }
}
以及以下实现:
// Broken - violates Liskov substitution principle (page 40)
@Override public boolean equals(Object o) {
if (o == null || o.getClass() != getClass())
return false;
Point p = (Point) o;
return p.x == x && p.y == y;
}
好的,违反了,然后呢?我不明白。
【问题讨论】:
-
超类也不应该知道他的孩子,但对象知道字符串类^^ java 根本设计得不好。
-
@Zelldon 请详细说明,“对象知道字符串”是什么意思? (我没有遵循你的说法)
-
对象有
toString()方法。 -
我实际上不明白你的问题中需要“但是”。矛盾在哪里?
-
这是一个discussion,它显示了两难境地。