Java中==、equals() 的区别和 hashCode() 的关系
特性==equals()hashCode()用途比较基本类型值或对象引用比较对象内容生成对象的哈希码比较对象基本类型和引用类型只能是对象只能是对象默认行为比较值或引用比较引用(与==相同)基于对象地址可重写否是是与集合的关系无关用于contains()等操作用于哈希集合的存储和查找==比较值或引用,equals()比较内容,hashCode()生成哈希码重写equals()时必须重写hashCod
目录
在 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() 方法之间必须遵守的重要契约:
- 一致性:在应用程序执行期间,只要对象的
equals()比较所用的信息没有被修改,对同一个对象多次调用hashCode()必须返回相同的整数 - 相等性:如果两个对象根据
equals()方法是相等的,那么它们的哈希码必须相同 - 不等性:如果两个对象根据
equals()方法是不相等的,它们的哈希码不一定不同(但不同可以提高哈希表性能)
这个契约意味着:如果你重写了 equals() 方法,你必须同时重写 hashCode() 方法!
为什么需要遵守这个契约?
考虑使用 HashSet 或 HashMap 的情况:
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()等操作 |
用于哈希集合的存储和查找 |
关键要点:
==比较值或引用,equals()比较内容,hashCode()生成哈希码- 重写
equals()时必须重写hashCode() - 相等的对象必须有相同的哈希码
- 不相等的对象可以有相同的哈希码(哈希冲突),但会影响性能
正确理解这三者的关系,可以帮助我们避免许多常见的 Java 编程错误,特别是在使用集合类时。
更多推荐

所有评论(0)