Java中对于所有对象都通用的方法之——equals

时间:2022-05-19 22:30:07

Object:所有类的超类

Object类是Java中所有类的超类,在Java中每个类都是由它扩展来的。

尽管Object是一个具体的类,但是设计它主要是为了扩展。它所有的非final方法(equals、hasCode、toString、clone和fanalize)都有明确的通用约定(general contract),因为它们被设计成是要被覆盖(Override)的.


equals

Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断两个对象是否具有相同的引用。
然而,对于多数类来说,这种判断并没有什么意义。因为当判断对象是否相等时,经常需要检测两个对象状态的相等性。

通用约定 [JavaSE6]

  • 自反性。对于任何非null的引用值x,x.equals(x)必须返回true。
  • 对称性。对于任何非null的引用值x和y,如果y.equals(x)返回true时,x.equals(y)必须返回true。
  • 传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true时,x.equals(z)也必须返回true。
  • 一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致的返回false。
  • 对于任何非null的引用值x,x.equals(null)必须返回false。

实现高质量equals的诀窍

  • 1)显示参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。
  • 2)使用==操作符检测this与otherObject是否引用同一个对象:
    if(this == otherObject) return true;
  • 3)检测otherObject是否为null,如果为null,返回false。这项检测时必要的。
    if(otherObject == null) return false;
  • 4)比较this与otherObject是否属于同于一个类。
    如果equals的语义在每个子类中有所改变,就使用getClass检测:
    if(getClass() != otherObject.getClass()) return false;
    如果所有的子类都拥有统一的语义,就使用instanceof检测:
    if(!(otherObject instanceof ClassName)) return false;
  • 5)将otherObject转换为相应的类类型变量:
    ClassName other == (ClassName) otherObject
  • 6)现在开始对所有需要比较的域进行必较了。使用==比较基本类型域,使用equals比较对象域。如果所有的域都匹配,就返回true;否则返回false。
    return field1 == other.field1&&Objects.equals(field2, other.field2)&&···;
  • 7)如果在子类中重新定义equals,就要在其中包含super.equals(other)。

for example

class Employee
{
public boolean equals(Object otherObject)
{
//a quick test tot see if the objects are identical
if(this == otherObject) return true;

//must return false if the explicit parameter is null
if(otherObject == null) return false;

//if the classes don't match, they can't be equal
if(getClass() != otherObejct.getClass())
return false;

//now we know otherObject is non-null Employee
Employee other = (Employee) otherObject;

//test whether the fields have identical values
return name.equals(other.name)
&& salary == other.salary
&& hireDay.equals(other.hireDay);
}
}
class Manager extends Employee
{

public boolean equals(Obejct otherObject)
{
if(!super.equals(otherObject))
return false;
//super.equals checked that this and otherObject belong to the same class
Manager other = (Manager) otherObject;
return bonus == other.bonus;
}
}

告诫

  • 覆盖equals时总要覆盖hashCode。
  • 不要企图让equals方法过于智能。
  • 不要将equals声明中的Object对象替换为其他的类型。(否则就没有覆盖Object.equals.)

未完待续
参考《Java核心技术》、《Effective Java》