首先要明确一个问题,Object类中的equals方法是怎样判断两个对象是否相等的呢?让我们来看看它的源代码:
public boolean equals(Object obj) |
不难看出,它仅仅判断了两个对象的引用是否相等,这在很多情况下并没有太大的实际意义。比如,我们需要一个比较两个字符串是否相等,在String类中就覆盖了这个方法。标准的java类库中有超过150个equals方法的实现。然而java语言规范要求equals方法具有以下性质:
- 自反性:对于任何非空引用x, x.equals(x)返回true。
- 对称性:对于任何非空引用x和y, 当且仅当y.equals(x)返回true时,x.equals(y)返回true。
- 传递性:对于任何引用x,y和z,如果x.equals(y)返回true并且y.equals(z)也返回true,那么x.equals(z)应该返回true。
- 一致性:如果x和y引用的对象没有改变,那么x.equals(y)的重复调用应该返回同一结果。
- 对于任何非空引用x, x.equals(null)应该返回false。
这5条规则显示良好的逻辑性,想要写好自己的equals方法,必须满足它们。那么如何才能做到这些规则呢?
假设当前equals方法传进来的参数名为otherObject,
- 测试this是否与otherObject相等。
- 测试otherObject是否为null,如果是,一定要返回false。
- 测试this通otherObject是否同属于一个类。这是为了满足规则2。
- 把otherObject强制转换为另一个变量(这里称为other):Classname other = (Classname) otherObject。然后比较所有的字段。使用 == 比较基本类型字段,使用equals方法比较对象字段。如果所有的字段都匹配返回true,否则返回false。
下面举一个简单的例子:
class TestEqual{ int number; String s; public boolean equals(Object otherObject){ //首先看看这两个对象引用是否相等 if (this == otherObject) return true; //这是为了满足规则5 if(otherObject == null) return false; //如果两个对象所属类型不同,它们不可能相等 if(getClass() != otherObject.getClass()) return false; TestEqual other = (TestEqual)otherObject; //比较所有字段 return s.equals(otherObject.s) && number == otherObject.number; } } |
这个例子虽然很简单,但却清晰地反映出了以上所说的要点。
还有一个需要注意的地方是,在子类中,首先要调用超类的equals方法,如果这项测试无法通过,那么两个对象不可能相等。也就是:
if(!super.equals(otherObject)) return false; |
到这里相信大家已经对编写自己的equals方法有了一定的认识,只要在平时写程序的时候多注意一下,写好它并不难。
再来看看本文的第二大主题: