覆盖equals有时看起来很简单,可是许多覆盖方式会产生错误。通常来讲须要知足如下条件:
java
1:类的每一个实例本质上都是惟一的。eclipse
2:不关心类是否提供了“逻辑相等(logical equality)”的测试功能。 ide
3:超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。 测试
4:类是私有的或是包级私有的,能够肯定他的equals方法永远不会被调用。this
首先看个例子spa
public final class CaseInsensitiveString { private final String s; public CaseInsensitiveString(String s) { if (s == null) throw new NullPointerException(); this.s = s; } // Broken - violates symmetry! @Override public boolean equals(Object o) { if (o instanceof CaseInsensitiveString) return s.equalsIgnoreCase(((CaseInsensitiveString) o).s); if (o instanceof String) // One-way interoperability! return s.equalsIgnoreCase((String) o); return false; } public static void main(String[] args) { CaseInsensitiveString cis = new CaseInsensitiveString("Polish"); String s = "polish"; System.out.println("cis.equals(s): "+cis.equals(s)); System.out.println("s.equals(cis):"+s.equals(cis)); }
该代码运行结果: cis.equals(s): true s.equals(cis):false
这个类的equals意图很好,它企图与普通的字符串(String)进行互相操做,正如你们所料,cis.equals(s)返回true,由于cis是对象,调用的是CaseInsensitiveString类中的equals。而s.equals(cis)返回false。是由于s字符串,默认它的equals调用的是String类中的equals方法,因此返回false。code
实现高质量equals方法的诀窍: 对象
一、使用==操做符检查“参数是否为这个对象的引用”。 继承
二、使用instanceof操做符检查“参数是否为正确的类型”。 ip
三、把参数转换成正确的类型。
四、对于该类的每一个“关键(significant)”域,检查参数中的域是否与该对象中对应的域相匹配。
这点myeclipse自动生成的并不彻底完美,myeclipse生成以下:
else if (!name.equals(other.name))
return false;
可是,这条是要求你改为:
else if (name != other.name && !name.equals(other.name))
return false;
五、当你编写完成了equals方法以后,应该会问本身三个问题:他是否的对称的、传递的、一致的。
(覆盖equals时总要覆盖hashcode;不要企图让equals方法过于智能;不要将equals声明中的Object对象替换为其余的类型。)
尽可能不要省略@Override。