我有以下代码
@Override
public boolean equals(Object o) {
if (!(o instanceof ColorPoint))
return false;
return super.equals(o) && ((ColorPoint) o).color == color;
}
我有以下
Point p = new Point(1, 2);
ColorPoint cp = new ColorPoint(1, 2, Color.RED);
ColorPoint
继承Point
。问题是当我p.equals(cp)
为什么返回true
时?我的意思是在最后一次回归时它会调用super.equal
但是在那个演员身上会发生什么?它在使用ColorPoint
@Override public boolean equals(Object o) {
if (!(o instanceof Point))
return false;
Point p = (Point)o;
return p.x == x && p.y == y;
}
这与Point类相同
答案 0 :(得分:3)
您使用equals
的{{1}}方法,而不是Point
的方法。
更改为ColorPoint
,您将获得cp.equals(p)
。
请注意,您不应以可能使其不对称的方式实现false
。如果要匹配类,请务必检查是否要扩展类:
equals
答案 1 :(得分:1)
除了其他答案之外,equals()
的实现违反了JavaDocs中定义的合同:
equals方法在非null对象引用上实现等价关系:
- ...
- 它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。
- ...
这意味着您不应检查o instanceof Point
,而是o.getClass() == getClass()
。通过实施,您在调用p.equals(cp)
和cp.equals(p)
时会得到不同的结果,从而违反了该合同。这可能会导致细微的错误,因为大多数收藏都依赖于合同。
答案 2 :(得分:0)
equals
已为ColorPoint
实施equals
方法。你在Point上调用false
。它只会检查两个坐标 - 而不是颜色。
如果致电cp.equals(p);
if
答案 3 :(得分:0)
类层次结构和equals()
不能很好地结合在一起。
如果使用equals()
在超类中实现instanceof
(以便子类可以等于超类),则可以通过对称打破equals()
的要求:
p.equals(cp) // true
cp.equals(p) // false
如果使用getClass().equals(other.getClass())
实现它,您将获得正确的合同,但阻止任何子类实例与您的实例相同 - 这可能是一个问题,例如当使用像Hibernate这样的ORM为你的类创建代理类时。
equals()
似乎在多个类中运行良好的唯一情况是,当您有一个接口并根据该接口的方法定义equals()
的合同时,那么编写所有实现,以便他们遵守合同并仅使用接口公开的信息。例如,可以在java.util.List
及其常见实现中看到这一点。