您的位置:

深入理解Java中的equals方法

Java中的equals方法是比较两个对象在逻辑上是否相等,相等返回true,不相等返回false。在默认情况下,equals用于比较两个对象的引用是否相等。也就是说,如果两个对象的引用指向同一个地址,那么equals返回true,否则返回false。但是在实际应用中,我们可能需要用到自定义的方式来比较两个对象的内容是否相等,本文将从以下几个方面对equals方法做详细的阐述。

一、equals方法与==运算符的区别

在Java中,==运算符用于比较两个变量或表达式的值是否相等,而equals方法用于比较两个对象在逻辑上是否相等。==运算符比较的是两个变量或表达式的值,即两者在内存中的存储地址是否相等。而equals方法比较的是两个对象的内容是否相等,并不关心两个对象在内存中的存储地址是否相等。 例如:
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";

System.out.println(str1==str2);//false,因为str1和str2的地址不同
System.out.println(str1==str3);//true,因为str1和str3的地址相同
System.out.println(str1.equals(str2));//true,因为str1和str2的内容相同
System.out.println(str1.equals(str3));//true,因为str1和str3的内容相同
在上面的例子中,由于字符串“hello”在Java中是常量,因此str1和str3都指向同一个地址,而str2则是通过new关键字新创建了一个字符串对象,因此与str1和str3的地址不同。因此通过==运算符比较str1和str2的值时返回false,而通过equals方法比较它们的内容时返回true。

二、equals方法的重写

在Java中,如果我们需要比较两个对象的内容是否相等,那么就需要重写equals方法。默认情况下,equals方法比较的是两个对象的引用是否相同,即比较两个对象的内存地址是否相等。而我们重写了equals方法,就可以通过自定的方式比较两个对象的内容是否相同。 通常情况下,我们要重写equals方法,就需要重写hashCode方法。因为在HashSet和HashMap等集合中,对象的hashCode用于定位对象在内存中存放的位置,如果多个对象的hashCode相同,那么它们将被放在同一个位置上,这样会影响查找和删除操作。 例如:
public class Person {
    private String name;
    private int age;
 
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;//判断类型是否相同,如果不同,返回false
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
在上面的例子中,我们重写了Person类的equals方法和hashCode方法。equals方法先判断传入的对象是否为null,如果是,则返回false。然后再判断两个对象是否引用同一个内存地址,如果是,则返回true,否则判断两个对象的类型是否相同,如果不同,则返回false。最后比较两个对象的内容是否相等,即姓名和年龄是否相等,如果相等则返回true,否则返回false。hashCode方法使用Objects类中的hash方法,对对象的name和age属性进行哈希计算,并返回计算结果。

三、equals方法与继承关系

在Java中,如果一个类没有重写equals方法,则其默认继承自Object类的equals方法。而Object类的equals方法比较的是两个对象的引用是否相等,即两个对象在内存中的地址是否相同。因此,如果一个类没有重写equals方法,则在比较对象时,其比较的是两个对象的内存地址,而不是内容是否相等。 例如:
public class Animal {
    private String name;
    private int age;
 
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
在上面的例子中,Animal类没有重写equals方法。因此,当比较两个Animal类型的对象时,其比较的是两个对象的引用地址,而不是两个对象的内容是否相等。如果我们将两个Animal对象分别存放在两个HashSet集合中,虽然它们的内容是相同的,但是由于它们在内存中存放的地址值不同,因此会被HashSet当做两个不同的元素来处理。 例如:
Animal animal1 = new Animal("Tom", 2);
Animal animal2 = new Animal("Tom", 2);
Set set = new HashSet<>();
set.add(animal1);
set.add(animal2);
System.out.println(set.size());//2,因为animal1和animal2在内存中的地址不同

  
因此,如果一个类需要用到equals方法进行对象比较,就必须重写这个方法。

四、equals方法的实现方式

实现equals方法的方式有两种,一种是手动编写equals方法,另一种是使用IDE自动生成EqualsAndHashcode方法。使用IDE自动生成EqualsAndHashcode可以减少手工编写equals方法的工作量。一般步骤是先在类中创建成员变量,并选中这些成员变量,然后通过IDE中的Generate选项自动生成equals方法和hashCode方法。 例如,在Eclipse中,我们可以通过以下步骤自动生成equals方法和hashCode方法: 选择源代码中的类或代码块,然后右键单击,选择Generate -> Equals and HashCode。 在Equals And HashCode Generation窗口中,勾选自动生成equals方法和hashCode方法,并选择需要参与equals比较和hashCode计算的属性,然后点击“OK”按钮。 IDE将自动生成equals方法和hashCode方法,将其添加到类中。

总结

equals方法用于比较两个对象在逻辑上是否相等,相等返回true,不相等返回false。默认情况下,equals方法比较的是两个对象的引用是否相等,即它们在内存中的存储地址是否相等。如果一个类需要比较对象的内容是否相等,则需要重写equals方法,并重写hashCode方法。在重写equals方法时,通常要考虑对象的类型、内容等因素,以实现自定义的比较方式。