1、Object类中默认的实现方式是:return this == obj。也就是说,只有this和obj引用同一个对象的时候,才会返回true
2、equals方法需要满足以下规则:
(1)、自反性:x.equals(x)应该返回true;
(2)、对称性: x.equals(y)为true,那么y.equals(x)也为true;
(3)、传递性:x.equals(y)为true,并且y.equals(z)为true,那么x.equals(z)也应该为true;
(4)、 一致性: x.equals(y)的第一次调用为true,那么第二次、第三次、第n次调用也应该为true,前提条件是在比较之前没有修改x也没有修改y;
(5)、对非空引用x, x.equals(null)返回false。
3、用一个demo简单介绍一下equals方法的编写
public class EqualsDemo
{
private String name;
private int age;
public EqualsDemo()
{
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
// 能执行到这里,说明obj和this同类且非null。
EqualsDemo p = (EqualsDemo) obj;
return age == p.age && (name == p.name || (name != null && name.equals(p.name)));
}
@Override
public int hashCode()
{
// 重写equals,也必须重写hashCode。具体后面介绍。
}
}
EqualsDemo的对象有二个字段,name和age,这2个字段代表了对象的状态,也会用在equals方法中作为评判的依据。
在equals方法中,首先将obj(传入对象的引用)和this做比较,节约执行时间,如果this 和 obj是 对同一个堆对象的引用,那么,他们一定是相等的。
接着,判断obj是否为null,如果是bull,一定不相等,因为既然当前对象this能调用equals方法,那么它一定不是null,非null和null当然不相等。
然后,比较2个对象的运行时类,是否为同一个类。不是同一个类,则不相等。getClass返回的是 this 和obj的运行时类的引用。如果他们属于同一个类,则返回的是同一个运行时类的引用。注意,一个类也是一个对象。
也有人使用下面方法替代上面比较运行时类的写法,应该避免这样做:
if(!(obj instanceof EqualsDemo))
return false; // avoid 避免!
因为它违反了规则中的对称性,例如;假设Dog类扩展了Animal类。这就会导致
animal.equls(dog) 返回true
dog.equals(animal) 返回false
仅当EqualsDemo类没有子类的时候,这样做才能保证是正确的。
按照第一种方法实现,那么equals只能比较同一个类的对象,不同类对象永远是false。但这并不是强制要求的。一般我们也很少需要在不同的类之间使用equals。
在具体比较对象的字段的时候,对于基本值类型的字段,直接用 == 来比较(注意浮点数的比较,这是一个坑)对于引用类型的字段,你可以调用他们的equals,当然,你也需要处理字段为null 的情况。对于浮点数的比较,我在看Arrays.binarySearch的源代码时,发现了如下对于浮点数的比较的技巧:
if ( Double.doubleToLongBits(d1) == Double.doubleToLongBits(d2) ) //d1 和 d2 是double类型
if( Float.floatToIntBits(f1) == Float.floatToIntBits(f2) ) //f1 和 f2 是d2是float类型
并不总是要将对象的所有字段来作为equals 的评判依据,那取决于你的业务要求。比如你要做一个家电功率统计系统,如果2个家电的功率一样,那就有足够的依据认为这2个家电对象等价了,至少在你这个业务逻辑背景下是等价的,并不关心他们的价钱啊,品牌啊,大小等其他参数。
最后需要注意的是,equals 方法的参数类型是Object,不要写错!
注释以上部分内容来自:
lulipro