知识点:
1.哪些情况下不需要覆盖equals方法。
2.什么情况下需要覆盖equals方法。
3.覆盖equals方法需要遵守的约定。
4.写equals方法的诀窍。
5.写equals方法的告诫。
6.Java类库中的equals方法。
Java Object对象的九个方法。他们分别是clone(), getClass(), toString(), equals(), wait(), hashcode(), notify(), notifyall(), finalize()。这章讨论equals(), hashcode(), toString(), clone() 四个方法和Comparable接口。
1.哪些情况下不需要覆盖equals方法。
a.类的每个实例本质上都是唯一的。比如Thread。它们不是代表值的类,也不需要做值上的比较。
b.不关心类的对象是否逻辑相等。
c.超类已经重写了equals方法,子类用着也比较合适。
d.类是私有的或是包级私有的,我解释一下这两个概念, 看下面代码:类In就是私有的,只有类One内部可以访问,类Two就是包级私有的,前面没有任何修饰符,同一个包间恶意访问。这种不对外部开放的类,如果确定equals方法不会被调用,可以不重写。当然如果不想让他们被调用,也可以重写,调用的时候抛异常。
public class One{
private class In {
}
}
class Two {
}
2.什么情况下需要覆盖equals方法。
很简单,类是值类,比如Integer, Date, Float等,对于他们对象的比较,我是想比较他们的值,并不是想知道这两个对象是不是同一个对象,就需要重写。
3.覆盖equals方法需要遵守的约定。
a.自反性
b.对称性
c.传递性
d.一致性
e.非null性
这五个特性的理解可自行看书,不作过多解释。
4.写equals方法的诀窍。
我们不可能按照第三条的五个约定来重写equals方法,这根本没法下手,按照下面诀窍来写,写完可以按照用上面五个约定来验证你的equals方法是否完美。
a.使用==操作符检查“参数是否为这个对象的引用”。如果是,返回true。如果引用都是一样,值肯定也是一样。
b.使用instanceOf操作符检查“参数是否为正确的类型”。如果不是,返回false。如果两个都不是同样类型的对象,值肯定不一样,不过两个对象实现同一个接口,我们应该判断参数是否为同一样的接口。
c.参数转换为正确的类型。
d.每一个关键域进行比较,全部相等则返回true。
5.写equals方法的告诫。
下面三个问题,我们在写的时候要注意:
a.覆盖equals时总要覆盖hashCode。我本身认为这条不是一定需要的,如果你的对象不会作为Map等类型的key,只有比较的功能,也可以不覆盖。但你要保证别人不会用这个类来作为Map的Key。如果别人这样做了,就会有问题。(我后面会详细讲解Map相关的知识)
b.不要把equals方法弄的过与复杂。其实就是简单的对象比较,不要把什么对象都弄来比较。
c.不要将equals神明中的Object对象替换为其它对象。那样就不是重写了,是重载了。
6.Java类库中的equals方法。
这里我们只看三个类,Object, String和Integer。看下面代码,Object的equals方法就是比较引用是不是一样。Integer的是,先看对象是不是Integer类,然后比较他们的值是否相等。String的是,先看对象的引用是不是一样,然后看对象类型是不是String,然后一个个字符比较。基本就是按照上面写equals方法的诀窍来写的。大家工作中碰到可以按照这种方式来写。
Object的equals方法
public boolean equals(Object obj) {
return (this == obj);
}
Integer的equals方法
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
String的equals方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}