我知道不可能扩展一个覆盖方法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));
打印:
真 假
以同样的方式可以证明该方法不具有传递性。但是,当我将对象作为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
使用哪种方法来比较密钥?
答案 0 :(得分:6)
这可能是因为eclipse生成的hashcode()会考虑ColourPoint的颜色字段,因此点和颜色点会散列到不同的存储桶,并且永远不会与equals()进行比较。
请注意,这意味着hashcode()的契约被破坏 - a.equals(b)== true的两个对象正在生成不同的哈希码。基本上,不要这样做!
Scala语言对此有一个有趣的看法,使用canEqual方法来确定两个对象是否可以相等。请查看here。