这个 equals() 方法 return 怎么会是真的?

How can this equals() method return true?

我正在阅读 Effective Java 中的 equals 合同,在传递部分我遇到了疑问,在下面的代码中:

public class Point {
    private final int x;
    private final int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

现在我们有了这个

@Override 
public boolean equals(Object o) {
    if (!(o instanceof Point))
        return false;
    Point p = (Point)o;
    return p.x == x && p.y == y;
}


public class ColorPoint extends Point {
    private final Color color;
    public ColorPoint(int x, int y, Color color) {
        super(x, y);
        this.color = color;
    }
    // Remainder omitted
}
// Broken - violates symmetry!
@Override 
public boolean equals(Object o) {
    if (!(o instanceof ColorPoint))
        return false;
    return super.equals(o) && ((ColorPoint) o).color == color;
}

ColorPoint cp = new ColorPoint(1, 2, Color.RED);

Point p = new Point(1, 2);

如果我 运行 p.equals(cp) ,它应该 return false 因为
return super.equals(o) && ((ColorPoint) o).color == color; 对两个 class 都无效,因为 point class 不包含变量 Color

为什么书上写的是真的?

正如您在代码中清楚看到的那样:

ColorPoint cp = new ColorPoint(1, 2, Color.RED);
Point p = new Point(1, 2);  // create a Point
p.equals(cp)                // call Point::equals

你调用Point::equals()方法...不比较颜色,想想Point 没有颜色属性.

但是无论如何,您可以使用 cp.equals(p):

将两个元素与 ColorPoint::equals 进行比较
ColorPoint cp = new ColorPoint(1, 2, Color.RED);
Point p = new Point(1, 2);          // create a Point
System.out.println(p.equals(cp));   // call Point::equals
System.out.println(cp.equals(p));   // call ColorPoint::equals

将输出:

true
false

注意:小心!!!
这个false不是针对不同的color属性,是因为p不是instanceof ColorPoint!!。


编辑:

thanks a lot , thats bad from my side ..i should have figured it :(

嗯,当你在这种情况下有经验时,更容易理解,但一开始可能很难理解。在这种情况下,遵循我调试的应用程序的流程,但您可以更轻松、更快地实现此信息添加打印语句。

例如:

ColorPoint::equals

@Override
public boolean equals(Object o) {
    System.out.println("equals ColorPoint");
    if (!(o instanceof ColorPoint))
        return false;
    return super.equals(o) && ((ColorPoint) o).color == color;
}

Point::equals

@Override
public boolean equals(Object o) {
    System.out.println("equals Point");
    if (!(o instanceof Point))
        return false;
    Point p = (Point) o;
    return p.x == x && p.y == y;
}

同样的测试程序会输出:

equals Point
true
equals ColorPoint
false

这为您提供了有关正在发生的事情的线索!