首先介绍一下Java中equals通用约定,分别是:自反性、对称性、一致性、传递性。
检查自反性的通用方法:
将对象扔到List里,然后看List.contains()是否返回true。
首先来看一个违反对称性的例子:
public class CaseInsesitiveString { private final String s; public CaseInsesitiveString(String s) { if(s == null){ throw new NullPointerException(); } this.s = s; } @Override public boolean equals(Object obj) { if(obj instanceof CaseInsesitiveString){ return s.equalsIgnoreCase(((CaseInsesitiveString) obj).s); } if(obj instanceof String){ return s.equalsIgnoreCase((String) obj); } return false; } }
public class EqualTest { public static void main(String[] args) { CaseInsesitiveString str = new CaseInsesitiveString("Hello"); String s = "hello"; System.out.println(str.equals(s)); System.out.println(s.equals(str)); List<CaseInsesitiveString> list = new ArrayList<CaseInsesitiveString>(); list.add(str); System.out.println(list.contains(s)); } }
原因是:String类中的equals并不知道大小写是否相等。
解决办法:
@Override public boolean equals(Object obj) { return obj instanceof CaseInsesitiveString && s.equalsIgnoreCase(((CaseInsesitiveString) obj).s); }
再来看一个违反传递性的例子:
public class ColorPoint extends Point { private final Color color; public ColorPoint(int x, int y, Color color) { super(x, y); this.color = color; } @Override public boolean equals(Object obj) { if(!(obj instanceof Point)) return false; if(!(obj instanceof ColorPoint)) return obj.equals(this); return super.equals(obj) && ((ColorPoint) obj).color == color; } }
ColorPoint point = new ColorPoint(1,2,Color.BLUE); Point p = new Point(1,2); ColorPoint colorPoint = new ColorPoint(1,2, Color.RED); System.out.println(point.equals(p)); System.out.println(p.equals(colorPoint)); System.out.println(point.equals(colorPoint));
解决办法:
public class ColorPointNew { private final Point point; private final Color color; public ColorPointNew(int x, int y, Color color) { if(color == null){ throw new NullPointerException(); } this.color = color; point = new Point(x,y); } @Override public boolean equals(Object obj) { if(!(obj instanceof ColorPointNew)) return false; ColorPointNew point = (ColorPointNew) obj; return point.point.equals(point) && point.color == color; } public Point asPoint(){ return point; } }