java equals函数用法详解


在Java中,`equals` 方法是一个用于比较两个对象是否“相等”的方法。它定义在 `java.lang.Object` 类中,因此所有的Java类都继承了这个方法。然而,默认情况下,`Object` 类的 `equals` 方法比较的是两个对象的引用是否相同,即它们是否是内存中的同一个对象。对于大多数应用来说,这种比较方式是不够的,因此很多类都会重写(Override)`equals` 方法来提供更有意义的相等性判断。

### `equals` 方法的基本规则

1. **自反性**:对于任何非空引用值 `x`,`x.equals(x)` 应该返回 `true`。

2. **对称性**:对于任何非空引用值 `x` 和 `y`,当且仅当 `y.equals(x)` 返回 `true` 时,`x.equals(y)` 也应该返回 `true`。

3. **传递性**:对于任何非空引用值 `x`、`y` 和 `z`,如果 `x.equals(y)` 返回 `true` 且 `y.equals(z)` 返回 `true`,那么 `x.equals(z)` 也应该返回 `true`。

4. **一致性**:对于任何非空引用值 `x` 和 `y`,只要对象中所比较的信息没有被修改,多次调用 `x.equals(y)` 应该一致地返回 `true` 或 `false`。

5. **对于任何非空引用值 `x`,`x.equals(null)` 应该返回 `false`**。

### 重写 `equals` 方法的最佳实践

1. **检查是否为同一个对象的引用**:首先使用 `==` 操作符检查两个对象是否是同一个实例。

2. **检查是否为 `null`**:如果比较的对象可能为 `null`,则先检查是否为 `null`。

3. **类型转换**:通常,我们需要将比较的对象转换为正确的类型,以便我们可以访问其字段。这一步是可选的,取决于你的具体实现。

4. **比较关键字段**:比较对象的所有关键字段。对于基本数据类型字段,可以直接使用 `==` 操作符;对于对象字段,则应该递归调用它们的 `equals` 方法。

### 示例


public class Person {
    private String name;
    private int age;

    // 构造函数、getter和setter省略

    @Override
    public boolean equals(Object obj) {
        // 1. 检查是否为同一个对象的引用
        if (this == obj) return true;
        
        // 2. 检查是否为null,以及是否为同一个类型
        if (obj == null || getClass() != obj.getClass()) return false;
        
        // 3. 类型转换(在这里可以省略,因为我们已经检查了类型)
        Person person = (Person) obj;
        
        // 4. 比较关键字段
        return age == person.age &&
               (name == person.name || (name != null && name.equals(person.name)));
    }

    @Override
    public int hashCode() {
        // 当你重写equals方法时,通常也需要重写hashCode方法
        // 这里省略了hashCode的实现细节
        return Objects.hash(name, age); // 假设Objects.hash是一个存在的方法
    }
}

注意:当你重写 `equals` 方法时,通常也需要重写 `hashCode` 方法,以保持 `hashCode` 方法的一般约定,即相等的对象必须具有相等的哈希码。这在使用哈希表(如 `HashMap`、`HashSet` 等)时非常重要。