equals(Object obj)做什么?

我经常在不同的地方找到一种平等的方法。 它实际上做了什么? 重要的是我们必须在每个class级都有这个吗?

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; } } 

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

默认情况下(在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(..)

检查javadoc以获取equals(..)方法所需的确切契约。

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

不同的类具有使2个对象“相等”的不同标准。 通常,如果equals()是同一个Object,则返回true:

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

这将返回false,尽管它们都是“对象”类,但它们不是同一个实例。 a.equals(a)将返回true。

但是,在类似String的情况下,您可以有2个不同的实例,但字符串相等性基于构成这些字符串的文字字符:

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

这些都是String的不同实例,但是第一个equals将返回true,因为它们都是“example” ,但第二个不会因为“example”不是“another”。

只有当存在相等的特殊情况时,您才需要为每个类重写equals(),例如包含3个字符串的类,但只有第一个String用于确定相等性。 在您发布的示例中,可能有另一个字段, description可能对于2个不同的“联系人”不同,但如果这4个条件匹配(第一个/最后一个名称和家庭/手机),则2个“联系人”将被视为相等数字),而匹配或不匹配的描述不会影响2个联系人是否相等。

除了Bozho提供的所有内容之外,还有一些其他事项需要注意,如果重写等于:

  • .equals(null)必须始终返回false – 即null不等于其他任何东西。 在您的代码的第二个if中处理此要求。

  • 如果确实某些东西 == 其他东西 ,那么还有东西 .equals( 别的东西 )也必须是真的。 (即相同的对象必须相等)代码的第一个if处理这个问题。

  • .equals应该是非空对象的对称,即a.equals(b)应该与b.equals(a)相同。 有时,如果您在父类和子类中进行子类化和重写equals,则此要求会中断。 通常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.equalTo(b) == truea.compareTo(b) == 0应为a.equalTo(b) == true

在许多IDE(例如Eclipse,IntelliJ IDEA,NetBeans)中,有一些function可以为您生成equalshashCode ,从而使您免于繁琐且可能容易出错的工作。

当想要通过对象找到合适的任何定义来知道两个对象是否相等时,使用equals方法。 例如,对于String对象,等效性是关于两个对象是否表示相同的字符串。 因此,类通常提供自己的equals实现,这些实现以该类的自然方式工作。

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

它使您能够重新定义哪些对象相等以及哪些不相等,例如,如果Person.ID相同或者权Weight相等,则可以将两个Person对象定义为相等,具体取决于应用程序中的逻辑。

请参阅: 覆盖java equals()方法的quirk