在 Java 中,equals() 方法用于比较两个对象是否“逻辑相等”,而不是比较引用地址(== 比较的是引用地址)。它是 Object 类的一个方法,可以被所有类继承和重写。以下是 equals() 的详细用法和注意事项:
1. equals() 方法的基本用法
1.1 Object 类的默认 equals() 方法
默认情况下,Object 类的 equals() 方法的行为与 == 相同,即比较两个对象的内存地址:
public boolean equals(Object obj) {
return (this == obj);
}
示例:
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1 == str2); // false(比较地址)
System.out.println(str1.equals(str2)); // true(比较内容)
1.2 重写 equals() 方法
为了让 equals() 比较对象的内容(而非地址),我们需要在自定义类中重写它。例如:
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 obj) {
if (this == obj) return true; // 如果是同一个对象,直接返回 true
if (obj == null || getClass() != obj.getClass()) return false; // 类型不同返回 false
Person person = (Person) obj; // 强制类型转换
return age == person.age && name.equals(person.name); // 比较属性
}
}
测试:
Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);
System.out.println(p1.equals(p2)); // true(比较 name 和 age)
2. equals() 方法的规范
重写 equals() 时,必须遵循以下规则(Java 规范):
- 自反性(Reflexive)
x.equals(x)必须返回true。 - 对称性(Symmetric)
如果x.equals(y)返回true,那么y.equals(x)也必须返回true。 - 传递性(Transitive)
如果x.equals(y)和y.equals(z)都返回true,那么x.equals(z)也必须返回true。 - 一致性(Consistent)
多次调用x.equals(y)应该始终返回相同的结果(除非对象被修改)。 - 非空性(Non-null)
x.equals(null)必须返回false。
3. 如何正确重写 equals()
3.1 标准重写模板
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // 1. 检查是否同一个对象
if (obj == null || getClass() != obj.getClass()) return false; // 2. 检查 null 和类型
MyClass other = (MyClass) obj; // 3. 强制类型转换
// 4. 比较所有关键字段
return field1.equals(other.field1)
&& field2 == other.field2
&& Objects.equals(field3, other.field3); // 使用 Objects.equals 避免 NPE
}
3.2 使用 Objects.equals() 避免 NullPointerException
如果字段可能为 null,可以用 Objects.equals() 替代 field.equals():
import java.util.Objects;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
MyClass other = (MyClass) obj;
return Objects.equals(this.name, other.name) // 安全比较
&& this.age == other.age;
}
4. equals() 与 hashCode() 的关系
- 规则:如果两个对象
equals()返回true,它们的hashCode()必须相同。 - 原因:
HashMap、HashSet等依赖hashCode()进行快速查找,如果违反此规则,会导致哈希表行为异常。
示例:
@Override
public int hashCode() {
return Objects.hash(name, age); // 自动生成 hashCode
}
5. 常见问题
5.1 equals() 和 == 的区别
| 方法 | 比较内容 | 适用场景 |
|---|---|---|
== | 内存地址 | 基本类型(int, char)或引用比较 |
equals() | 对象内容 | 对象比较(如 String、自定义类) |
5.2 String 的 equals() 与 equalsIgnoreCase()
equals():区分大小写。equalsIgnoreCase():不区分大小写。
示例:
String s1 = "Hello";
String s2 = "hello";
System.out.println(s1.equals(s2)); // false
System.out.println(s1.equalsIgnoreCase(s2)); // true
5.3 数组的 equals()
数组的 equals() 默认比较地址,应使用 Arrays.equals():
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
System.out.println(arr1.equals(arr2)); // false
System.out.println(Arrays.equals(arr1, arr2)); // true
6. 总结
equals()用于比较对象内容,默认比较地址,需重写。- 重写规则:自反、对称、传递、一致、非空。
- 必须同时重写
hashCode(),否则影响哈希集合的行为。 - 推荐使用
Objects.equals()和Objects.hash()避免NullPointerException。
正确使用 equals() 可以确保对象比较的准确性和一致性,是 Java 编程的重要基础。
全部评论(0)
还没有任何评论哟~