目录

1. == 操作符

2. equals() 方法

重写 equals() 方法

3. hashCode() 方法

hashCode() 与 equals() 的契约

为什么需要遵守这个契约?

4. 正确实现 equals() 和 hashCode()

5. 总结


在 Java 中,==equals()hashCode() 是三个密切相关但又容易混淆的概念。理解它们之间的关系对于编写正确的 Java 程序至关重要。

1. == 操作符

== 是 Java 中最基本的比较操作符,它用于比较两个变量的值:

  • 对于基本数据类型(int, double, boolean 等),== 比较的是它们的实际值
  • 对于引用类型(对象),== 比较的是对象的内存地址(即是否指向同一个对象)
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = str1;

System.out.println(str1 == str2); // false - 不同对象
System.out.println(str1 == str3); // true - 同一个对象

int a = 5;
int b = 5;
System.out.println(a == b); // true - 值相同

2. equals() 方法

equals() 是 Object 类中定义的方法,用于比较两个对象的内容是否相等:

public boolean equals(Object obj) {
    return (this == obj);
}

默认情况下,equals() 方法的行为与 == 相同,都是比较对象引用。但是,我们可以重写这个方法来实现自定义的相等性逻辑。

重写 equals() 方法

许多 Java 类(如 String、Integer 等)都重写了 equals() 方法:

String str1 = new String("hello");
String str2 = new String("hello");

System.out.println(str1 == str2);     // false
System.out.println(str1.equals(str2)); // true

当我们自定义类时,也应该根据需要重写 equals() 方法:

public class Person {
    private String name;
    private int age;
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Person person = (Person) obj;
        return age == person.age && Objects.equals(name, person.name);
    }
}

3. hashCode() 方法

hashCode() 也是 Object 类中的方法,它返回对象的哈希码值:

public native int hashCode();

哈希码是一个整数,用于在哈希表等数据结构中快速查找对象。

hashCode() 与 equals() 的契约

Java 规范规定了 hashCode()equals() 方法之间必须遵守的重要契约:

  1. 一致性:在应用程序执行期间,只要对象的 equals() 比较所用的信息没有被修改,对同一个对象多次调用 hashCode() 必须返回相同的整数
  2. 相等性:如果两个对象根据 equals() 方法是相等的,那么它们的哈希码必须相同
  3. 不等性:如果两个对象根据 equals() 方法是不相等的,它们的哈希码不一定不同(但不同可以提高哈希表性能)

这个契约意味着:如果你重写了 equals() 方法,你必须同时重写 hashCode() 方法!

为什么需要遵守这个契约?

考虑使用 HashSetHashMap 的情况:

Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);

Set<Person> set = new HashSet<>();
set.add(p1);
set.contains(p2); // 如果只重写equals()而不重写hashCode(),可能返回false

如果只重写 equals() 而不重写 hashCode(),两个相等的对象可能有不同的哈希码,导致在哈希集合中出现重复元素或查找失败。

4. 正确实现 equals() 和 hashCode()

Java 开发中,可以使用 IDE 自动生成或使用 Objects 工具类:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

5. 总结

特性

==

equals()

hashCode()

用途

比较基本类型值或对象引用

比较对象内容

生成对象的哈希码

比较对象

基本类型和引用类型

只能是对象

只能是对象

默认行为

比较值或引用

比较引用(与==相同)

基于对象地址

可重写

与集合的关系

无关

用于contains()等操作

用于哈希集合的存储和查找

关键要点:

  1. == 比较值或引用,equals() 比较内容,hashCode() 生成哈希码
  2. 重写 equals() 时必须重写 hashCode()
  3. 相等的对象必须有相同的哈希码
  4. 不相等的对象可以有相同的哈希码(哈希冲突),但会影响性能

正确理解这三者的关系,可以帮助我们避免许多常见的 Java 编程错误,特别是在使用集合类时。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐