我经常在不同的地方找到一个平等的方法。它实际上做了什么?重要的是我们必须在每个班级都有这个吗?
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;
}
}
答案 0 :(得分:33)
它重新定义了对象的“平等”。
默认情况下(在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 javadoc以获取equals(..)
方法所需的确切合约。
在许多情况下,当覆盖equals(..)
时,您还必须覆盖hashCode()
(使用相同的字段)。这也是在javadoc中指定的。
答案 1 :(得分:12)
不同的类对于使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的不同实例,但是第一个等于将返回true,因为它们都是“example”,但是第二个不会因为“example”不是“另一个”。< / p>
只有当存在相等的特殊情况时,您才需要为每个类重写equals(),例如包含3个字符串的类,但只有第一个String用于确定相等性。在您发布的示例中,可能有另一个字段description
,对于2个不同的“联系人”可能有所不同,但如果这4个条件匹配,则2个“联系人”将被视为相等(名/姓,和家庭/手机号码),而匹配或不匹配的描述不会影响2个联系人是否相等。
答案 2 :(得分:9)
除了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.compareTo(b) == 0
应该是真的,当且仅当a.equalTo(b) == true
在许多IDE(例如Eclipse,IntelliJ IDEA,NetBeans)中,有一些功能可以为您生成equals
和hashCode
,从而使您免于繁琐且可能容易出错的工作。
答案 3 :(得分:3)
当人们想要通过对象找到合适的任何定义来知道两个对象是否相等时,使用equals
方法。例如,对于String
个对象,等价关系是两个对象是否表示相同的字符串。因此,类通常提供自己的equals
实现,它以该类的自然方式工作。
equals
方法与==
的不同之处在于后者测试对象标识,即对象是否相同(不一定与等效对象相同)。
答案 4 :(得分:1)
它使您能够重新定义哪些对象相等以及哪些对象不相等,例如,如果Person
相同或Person.ID
,则可以将两个Weight
对象定义为相等根据应用程序中的逻辑,它是相等的。
答案 5 :(得分:0)
默认情况下,当我们不为自定义类提供实现时,将调用Object类的equals方法。 Object类的equals方法使用引用比较对象。
即a。等于(a);始终返回true。
如果我们要提供自己的实现,则将使用某些步骤来实现对象相等。
Reflexive: a.equals(a) always returns true;
Symmetric: if a.equals(b) is true then b.equals(a) should also be true.
Transitive: If a.equals(b), b.equals(c) then a.equals(c) should be true/false according to previous 2 result.
Consistent: a.equals(b) should be the same result without modifying the values of a and b.
注意:默认等于方法检查引用,即==运算符。
注意:对于任何非空参考值a,应返回a.equals(null) 错误。
public class ObjectEqualExample{
public static void main(String []args){
Employee e1 = new Employee(1, "A");
Employee e2 = new Employee(1, "A");
// if we are using equals method then It should follow the some properties such as Reflexive, Symmetric, Transitive, and constistent
/*
Reflexive: a.equals(a) always returns true;
Symmetric: if a.equals(b) is true then b.equals(a) should also be true.
Transitive: If a.equals(b), b.equals(c) then a.equals(c) should be true/false according to previous 2 result.
Consistent: a.equals(b) should be the same result without modifying the values of a and b.
Note: default equals method check the reference i.e. == operator.
Note: For any non-null reference value a, a.equals(null) should return false
*/
System.out.println(e1.equals(e1));
System.out.println(e1.equals(e2));
}
}
class Employee {
private int id;
private String name;
@Override
public String toString() {
return "{id ="+id+", name = "+name+"} ";
}
@Override
public boolean equals(Object o) {
// now check the referenc of both object
if(this == o) return true;
// check the type of class
if(o == null || o.getClass() != this.getClass()) return false;
// now compare the value
Employee employee = (Employee)o;
if(employee.id == this.id && employee.name.equals(this.name)) {
return true;
} else return false;
}
public int hashCode() {
// here we are using id. We can also use other logic such as prime number addition or memory address.
return id;
}
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
答案 6 :(得分:0)
还有一件事,地图使用equals方法确定对象是否作为键存在。 https://docs.oracle.com/javase/8/docs/api/java/util/Map.html