问题复现:
首先有一个Point类,重写了equals方法:
public class Point{
private final int x;
private final int y;
public Point(x,y){
this.x=x;
this.y=y;
}
@Override public boolean queals(Object o){
if(!(o instanceof Point){
return false;
}
Point p = (Point)o;
return p.x == x && p.y == y;
}
}
另有一个扩展类,ColorPoint继承Point类
public class ColorPoint{
private final Color color;
public ColorPoint(int x,int y,Color color){
super(x,y);
this.color=color;
}
}
这时候比较两个点的时候就有个问题:
Point point = new Point(1, 2);
ColorPoint cPoint = new ColorPoint(1, 2, Color.RED);
System.out.println(point.equals(cPoint)); // true
System.out.println(cPoint.equals(point); // false
可以发现equals方法违背了对称性原则,原因是Point的equals方法在接收ColorPoint类型的参数时,会将其当做Point进行比较,忽略了颜色的判断,认定两个类是相等的。
对此我们做出一些修改:
此时可修改equals方法,加入对颜色的判断:
if(!(o.instanceOf(Point))
return false;
//if o is a normal point,ignore color
if(!(o.instanceOf(ColorPoint))
return o.equals(this);
//if o is a colorPoint .do a full compation
return super.equals(o) && ((ColorPoint)o).equals(this.color);
这段代码修复了违背对称性的错误,但两个以上的点会有错误,比如 两个ColorPoint和一个Point作比较,如下:
ColorPoint cPointRed = new ColorPoint(1, 2, Color.RED);
Point point = new Point(1, 2);
ColorPoint cPointBlue = new ColorPoint(1, 2, Color.BLUE);
System.out.println(cPointRed.equals(point)); // true
System.out.println(point.equals(cPointBlue)); // true
System.out.println(cPointRed.equals(cPointBlue)); // false
这样又违背了传递性原则。这时候就有个建议:复合优先于继承
。
即不使用继承方式,而将'父类'包含在'子类'中
public class ColorPoint{
private final Point point;
private final Color color;
public ColorPoint(int x,int y,Color color){
point.x = x;
point.x = x
this.color = color;
}
public Point getPoint(){
return this.point;
}
//重写equals
@Override public boolean equals(Object o){
if(!(o instanceof ColorPoint){
return false;
}
ColorPoint cp = (ColorPoint)o;
//只有当坐标和颜色都相同才返回true;
return cp.point.equals(this.point) && cp.Color.equals(color);
}
}
当然,重写equals的时候一定记得重写hashCode~重写hashCode~重写hashCode~~de~de~de~
参考文献:《Effective Java》第二版 第8条 “覆盖equals方法时请遵守通用约定”
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。