第8条 覆盖equals时请遵照通用约定

覆盖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。 

相关文章
相关标签/搜索