首页 > 代码库 > java中如何实现一个优美的equals方法

java中如何实现一个优美的equals方法

  java中的任何类都从老祖宗Object中集成了equals方法,在编程实践中应用使用equals方法判断两个对象是否相同的场景无处不在,所以我们在实现自己的类是必须重写出一个优美的equals方法。

  1.   首先让我们来看看java语言规范中对equals方法的说明,一个equals方法应当满足如下几个特性:
  2.   自反性,对任何一个非空的引用x,x.equals(x)必须返回true;
  3.   对称性,对任何引用x和y来说,如果x.equals(y)返回true,那么y.equals(x)也必须返回true;
  4.   传递性,对任何引用x、y和z,如果x.equals(y)为true,y.equals(z)为true,那么x.equals(z)也必须为true;
  5.   一致性,如果x和y应用的对象没有发生改变,那么对x.equals(y)的重复调用都应当返回同样的值;
  6.   对任何非空引用x,e.equals(null)返回false。

  根据上面的6个条件,我们在重写一个equals方法时,可以遵循方法步骤:

  1.   将显示参数命名为otherObject,稍后转化为目标类型并命名为other;
  2.   检查this和otherObject是否相同;
  3.   检查otherObject是否为空,为空则返回false;
  4.   检查this和otherObject类型是否相同;
  5.   将otherObject转化为目标类型,并命名为other;
  6.   对类型中定义的属性进行比较,如果是基础数据类型使用==,如果是引用类型使用equals()。

  其中第4条在父子类之间进行比较是需要注意。如果父类中定义的equals中的功能在子类中发生了变化,使用if(this.getClass() != otherObject)进行类型比较;如果父类中equals中的功能在子类中发生了变化,使用if(!(otherObject instanceof this.getClass()))进行比较。例如,Employee类中name和salary两个属性,Manager类继承Employee,还拥有bonus属性。Employee中重写的equals方法比较name和salary是否相同,Manager继承Employee的equals方法后并没有再次进行重写,那么再进行Employee和Manager类的对象的equals比较时,使用 if(!(otherObject instanceof this.getClass()))return false;如果Manager中除了比较name和salary外还要比较bonus,即Manager要重写一个自己的equals方法,那么使用if(this.getClass()!=otherObject.getClass())return false;具体实现可以参考如下代码:

public boolean equals(Object otherObject){    //a quick test to see if the object are identical    if(this == otherObject){        return true;    }    //must return false if the explicit param is null    if(otherObject == null){        return false;    }    //if the class des‘t match, they cannot be equal    if(this.getClass() != otherObject.getClass()){        return false;    }    //now we the the otherObject is non-null Employee    Employee other = (Employee)otherObject;        //test whether the fields hava identical values    return name.equals(other.name)            &&salary == other.salary            &&hireDay == other.hireDay;}

  此处有一注意事项,在实现自己的equals方法时,如果声明为public boolean equals(Employee otherObject),即显示参数的类型不是Object类型,那么此方法不是继承自Object对象,而是Employee自己定义的一个方法。从Object继承的public boolean equals(Object otherObject)在java术语中交Overriding,自己定义的public boolean equals(Employee otherObject)叫Overloading。前者在运行期间动态绑定,后者在编译期间静态绑定。