在Java中,==
和 equals
方法用于比较对象,但它们之间存在本质的区别:
==
操作符
- 基本数据类型:
-
==
比较的是值是否相等。
int a = 10;
int b = 10;
System.out.println(a == b); // 输出 true
- 引用类型: 用于引用类型(如对象、数组)时,
==
比较的是两个对象的引用是否指向堆内存中的同一个地址,即它们是否是同一个对象的实例。即使两个对象的内容完全相同,如果它们在内存中的位置不同,==
也会返回false
。
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // 输出 false,因为 s1 和 s2 指向不同的对象
String s3 = "hello";
String s4 = "hello";
System.out.println(s3 == s4); // 输出 true,因为字符串常量池中的 "hello" 是同一个对象
equals
方法
- 默认实现:
equals
方法来源于 Object
类,所有Java类都默认继承了这个方法。在 Object
类中,默认的 equals
实现实际上就是调用 ==
比较对象的引用,这与直接使用 ==
没有区别。
public boolean equals(Object obj) {
return (this == obj);
}
- 重写
equals
方法:
- 但是,许多类(如
String
, Integer
, Date
等)重写了 equals
方法,以便根据对象的内容而非引用进行比较。这意味着,即使两个对象位于不同的内存位置,只要它们的内容(根据类的具体定义)相等,equals
就会返回 true
。
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2)); // 输出 true,因为内容相同
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
System.out.println(i1.equals(i2)); // 输出 true,因为值相同
- 重写
equals
方法时,通常需要遵守合同(Contract): - 自反性(Reflexive):
x.equals(x)
必须为 true
。 - 对称性(Symmetric):
x.equals(y)
为 true
,则 y.equals(x)
也必须为 true
。 - 传递性(Transitive):如果
x.equals(y)
且 y.equals(z)
,那么 x.equals(z)
也必须为 true
。 - 一致性(Consistent):多次调用
x.equals(y)
应该得到同样的结果,前提是对象的内部状态没有改变。 - 非空性(For any non-null reference value x, x.equals(null)
必须返回
false`。
示例
假设我们有一个 Person
类,重写了 equals
方法:
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 obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person other = (Person) obj;
return this.name.equals(other.name) && this.age == other.age;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
public static void main(String[] args) {
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Alice", 30);
Person p3 = p1;
System.out.println(p1 == p2); // 输出 false,因为 p1 和 p2 是不同的对象
System.out.println(p1 == p3); // 输出 true,因为 p1 和 p3 是同一个对象
System.out.println(p1.equals(p2)); // 输出 true,因为内容相同
System.out.println(p1.equals(p3)); // 输出 true,因为内容相同
}
}
总结来说,==
主要用于比较基本类型值或判断两个引用是否指向同一对象,而 equals
用于比较对象的内容是否相等,尤其是当类重写了 equals
方法时。在比较对象时,优先考虑使用 equals
方法,除非你确实需要比较引用的同一性。