effective java笔记------重载equals方法

来源:互联网 发布:何为会穿衣服知乎 编辑:程序博客网 时间:2024/04/19 09:21

什么时候重载equals方法?

我们先来看一看equals()方法在Object类中的实现:

public boolean equals(Object obj) {return (this == obj);    }
在Object类中,equals()方法用于判断两个引用是否指向同一个对象,因此,如果你的目的正是如此,就大可不必费力重载这个方法了.这种方法的实现使用与代表活动实体而不是"值"的类,比如Thread.

因此,需要重载equals()的类就被限制在值类范畴,因为这时候用户不是想判断两个引用是否指向同一个对象,而是想判断这两个引用的值是否"逻辑相等".

但是下面两种情况,即使该类是值类,equals()方法也不需要被重载:

1.实例受控类-------每个值最多只存在一个对象.

2.枚举类

对于上述两种类,判断值相等和判断实例相等实际上是一回事.


重载equals()方法要遵循的四个原则

当我们真正需要重载一个equals()方法时应该如何做呢?java规范里之处equals()重载时要遵守五个原则:

1.自反性(reflexive):即x.equals(x)总是返回true,其实这条很难违反.

2.对称性(symmetic):如果x.equals(y)返回true,那么y.equals(x)也应该返回true,反之亦然.

3.传递性(transitive):如果x.equals(y)返回true,y.equals(z)也返回true,那么x.equals(z)也应该返回true

4.一致性(consistent):如果x.equals(y)返回true,在x和y中的信息不发生改变的情况下,多次调用x.equals(y)都应该返回true.

5.非空性:即x.equals(NULL)永远返回false,没有对象和NULL相等


如何实现高质量的equals()方法?

1.“==”检测和instanceof检测:一个重载的equals()方法通常会在开始时进行一下两项检测

@overridepublic boolean equals(object o) { //参数类型必须是object,否则就不是重载而是新方法了    if(o == this){                //当比较操作比较昂贵时,值得这么做        return true;    }    if(!o instanceof ClassA){     //确保下面的强制类型转换可以正常进行        return false;    }    ClassA a = (ClassA) o;//......}

2.比较类中的“关键”域,避免冗余域的比较

例如两个矩形的长宽相等,那么它的面积自然相等,这是就不要在equals方法中增加比较面积的步骤

3.由于Float.NaN,-0.0f等常量的存在,double和float两种基本类型的比较要使用他们各自的compare()方法,其他基本类型的域可以直接使用“==”比较

4.某些对象引用域包含NULL可能是合法的,此时应采用如下实现

(field == null ? o.field == null : field.equals(o.field));
5.如果数组是关键域,并且每个元素都很重要,那么要使用Arrays.equals方法

6.测试,一定要测试

编写完成后,一定要测试方法是否满足上面五个原则!!!


其他注意事项

1.重载equals方法后一定要覆盖hashCode方法(后面会讲)

2.不要让equals方法过于智能,过犹不及,我们无法在扩展可实例化类的同时,既增加新的值组件,同时又能满足equals约定,是不可能的。除非愿意放弃面向对象的抽象所带来的优势


原创粉丝点击