2

我知道当有人在子类中添加新方面时,不可能扩展一个覆盖该方法的类equals()并保持它“保留”。类及其子类的常见示例说明了Point它:

public class Point {

    Double d1;
    Double d2;

    public Point(double d1, double d2){
        this.d1 = d1;
        this.d2 = d2;
    }
}

public class ColorPoint extends Point {

    String color;

    public ColorPoint(double d1, double d2, String s) {
        super(d1, d2);
        color = s;
    }
}

如果我们有 Eclipse 来创建方法equals()hashCode(),它还考虑到 的情况下的颜色属性ColorPoint。因此,该equals()方法被证明是不对称的。编码:

Point p1 = new Point(2,2);
ColorPoint cp1 = new ColorPoint(2, 2, "blue");

System.out.println(p1.equals(cp1));
System.out.println(cp1.equals(p1));

印刷:

真假

以同样的方式可以证明该方法不是传递的。但是,当我将 Objects 作为 a 中的键传递时HasMap,无论我传递它们的顺序如何,它都会将它们识别为不同的。编码:

Point p1 = new Point(2,2);
Point p2 = new Point(3.1,3.1);
ColorPoint cp1 = new ColorPoint(2, 2, "blue");
ColorPoint cp2 = new ColorPoint(3.1,3.1, "red");


Map<Point, Integer> map = new HashMap<>();
map.put(cp2, 4); map.put(cp1, 3);
map.put(p1, 1); map.put(p2, 2); 

System.out.println(map.size());

即使我以另一个顺序传递对象,也总是打印 4。这是预期的吗?Map那么,为了比较密钥,使用了哪种方法?

4

1 回答 1

6

这可能是因为eclipse生成的hashcode()考虑了ColourPoint的color字段,所以points和colorpoints hash到不同的bucket中,从不与equals()比较。

请注意,这意味着 hashcode() 的合同被破坏 - a.equals(b) == true 的两个对象正在生成不同的哈希码。基本上,不要这样做!

Scala 语言对此有一个有趣的看法,使用 canEqual 方法来确定两个对象是否永远相等。在这里查看。

于 2013-05-20T14:16:59.710 回答