2011-12-01 72 views
12

我经常在不同的地方发现一个equals方法。它实际上做了什么?我们必须在每个班级都有这个重要吗?equals(Object obj)做什么?

public boolean equals(Object obj) 
    { 
    if (obj == this) 
    { 
     return true; 
    } 
    if (obj == null) 
    { 
     return false; 
    } 
    if (obj instanceof Contact) 
    { 
     Contact other = (Contact)obj; 
     return other.getFirstName().equals(getFirstName()) && 
       other.getLastName().equals(getLastName()) && 
       other.getHomePhone().equals(getHomePhone()) && 
       other.getCellPhone().equals(getCellPhone()); 

    } 
    else 
    { 
     return false; 
    } 
} 
+4

我假设你已经看过了很清楚的文档:http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html [向下滚动到equals()作为直接链接似乎不适用于commments]。 – NPE

回答

31

它重新定义了对象的“平等”。

默认情况下(在java.lang.Object定义),一个目的是等于仅当它是同一个实例的另一个对象。但是当你覆盖它时你可以提供自定义的相等逻辑。

例如,java.lang.String通过比较内部字符阵列限定平等。这就是为什么:

String a = new String("a"); //but don't use that in programs, use simply: = "a" 
String b = new String("a"); 
System.out.println(a == b); // false 
System.out.println(a.equals(b)); // true 

即使您可能不需要测试类似的平等,您使用的类。例如,List.contains(..)List.indexOf(..)的实现使用.equals(..)

检查the javadocequals(..)方法所需的精确合同。

在许多情况下,当覆盖equals(..)时,还必须覆盖hashCode()(使用相同的字段)。这也是在javadoc中指定的。

1

它使你重新定义哪些对象相等并且不是,例如,你可以限定两个Person对象作为等于如果Person.ID是相同的,或者如果Weight等于取决于在应用程序中的逻辑。

看到这个:Overriding the java equals() method quirk

11

不同类别有不同的标准,是什么让两个对象“相等”。通常情况下,equals()方法返回true,如果是相同的对象:

Object a = new Object(); 
Object b = new Object(); 
return(a.equals(b)); 

这将返回false沉绵他们都是“对象”类,它们是不一样的实例。 a.equals(a)将返回true。

然而,就像一根绳索的情况下,你可以有2个不同的实例,但字符串平等是基于文本字符组成的字符串:

String a = new String("example"); 
String b = new String("example"); 
String c = new String("another"); 
a.equals(b); 
a.equals(c); 

这些都是不同的字符串的情况,但第一个等于将返回true,因为它们都是“示例”,但第二个不会因为“示例”不是“另一个”。

你不会需要重载equals()为每类,只有当平等的特殊情况,如包含3串类,但只有第一个字符串是用于确定平等。在您发布的例子,有可能是另一个领域,description这可能是2个不同的“联系人”不同,但2“联系人”会被认为是相等的,如果这4个标准的比赛(第一/姓氏和家庭/手机数字),而匹配或不匹配的描述不会影响2个联系人是否相等。

3

equals方法被用来当一个人想知道,如果两个物体是由什么定义的对象找到合适的等价物。例如,对于String对象,等同性是关于两个对象是否表示相同的字符串。因此,班级通常提供自己的实施方案,这种方式对于该班级来说是自然的。

equals方法与==的不同之处在于后者测试对象标识,即对象是否相同(不一定等同)。

8
从Bozho放弃一切

之外,还有一些额外的事情需要注意,如果重载等于:

  • 东西.equals(null)必须始终返回false - 即空不等于别的。如果您的代码在第二秒钟内处理此要求。

  • ,如果这是真的,东西 == 别的,然后还东西.equals(别的)也必须是真实的。 (即相同的对象必须相同)代码的第一个如果处理此问题。

  • .equals应该是非空对象的对称,即a.equals(b)应该与b.equals(a)相同。有时,如果您在父类和子类中进行子类化和重写equals,则此要求会中断。通常等于包含像if (!getClass().equals(other.getClass())) return false;这样的代码,至少可以确保不同的对象类型彼此不相等。

  • 如果您覆盖equals您还必须覆盖hashCode,以使下列表达式成立:if (a.equals(b)) assert a.hashCode() == b.hashCode()。即两个彼此相等的对象的哈希码必须相同。请注意,相反情况并非如此:具有相同散列码的两个对象可能彼此相等,也可能不相等。通常情况下,通过从用于确定对象的相等性的相同属性派生hashCode来处理此要求。

在你的情况,hashCode方法可能是:

public int hashCode() { 
    return getFirstName().hashCode() + 
    getLastName().hashCode() + 
    getPhoneHome().hashCode() + 
    getCellPhone().hashCode(); 
} 
  • 如果实现Comparable两个对象,如果它们是小相比,体积较大,或彼此相等,a.compareTo(b) == 0应当且仅当如果a.equalTo(b) == true

在许多IDE(例如Eclipse,IntelliJ IDEA,NetBeans)中,有一些特性g为你提供equalshashCode,从而避免你繁琐而且可能容易出错的工作。

相关问题