String#equals() 和 Object#equals() 的区别
在面试中,如果被问到 String#equals() 和 Object#equals() 的区别,主要是要理解它们在不同情况下的行为和实现。下面是它们的区别以及实现的细节:
1. Object#equals() 方法
定义:
Object#equals()是 Java 中所有类的基类Object中的一个方法。所有的类都继承了这个方法。如果没有重写它,默认的行为是比较引用是否相等,即比较对象的内存地址是否相同。
默认实现:
Object#equals()的默认实现通过==来比较两个对象的引用是否相同,只有当两个引用指向同一个内存地址时,返回true。
代码:
public boolean equals(Object obj) {
return (this == obj);
}
特点:
- 默认实现仅仅比较对象的内存地址(引用相等),不考虑对象的内容是否相同。
- 如果没有重写
equals()方法,那么Object#equals()就是用来判断引用相等的。
例子:
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println(obj1.equals(obj2)); // false,因为 obj1 和 obj2 是不同的对象
2. String#equals() 方法
定义:
String#equals()是String类中重写过的equals()方法。它用来比较两个字符串的内容是否相同,而不是引用是否相同。
实现:
String#equals()方法重写了Object#equals(),它会比较两个字符串的字符序列是否完全相同。
代码:
public boolean equals(Object obj) {
if (this == obj) return true; // 引用相等
if (obj == null || getClass() != obj.getClass()) return false; // 类型检查
String other = (String) obj;
return value.equals(other.value); // 比较字符内容
}
特点:
String#equals()比较的是字符串内容是否完全相同,而不是比较内存地址。- 即使两个字符串是通过不同的方式创建的,只要它们的内容相同,
equals()返回true。
例子:
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2)); // true,因为它们的内容相同
3. 主要区别总结
| 特性 | Object#equals() | String#equals() |
|---|---|---|
| 默认行为 | 比较两个对象的内存地址(引用相等) | 比较两个字符串的内容(字符序列相等) |
| 使用场景 | 通常用于比较对象的引用是否相等 | 用于比较字符串的内容是否相同 |
| 重写情况 | 默认实现,若不重写则按引用比较 | 已重写,比较字符串内容 |
| 返回值 | 仅在两个引用指向同一个内存地址时返回 true | 在两个字符串的字符序列相同的情况下返回 true |
| 比较内容 | 内存地址 | 字符内容 |
4. 面试回答要点
Object#equals()是 Java 中所有类的基类Object中的默认方法,比较的是引用是否相同,默认实现是通过==比较对象的内存地址。String#equals()是String类重写过的equals()方法,比较的是字符串的内容(字符序列)是否相同。- 需要注意,
String类中的equals()方法更具体地判断字符串内容是否相等,且它不会考虑两个字符串是否是相同的对象实例(即它比较的是内容而非内存地址)。
5. 常见的面试题变体
- 如果没有重写
equals()方法,String和Object的equals()会有什么区别? - 如果
String没有重写equals()方法,它会使用Object类的默认实现,比较的是引用是否相等,而不是内容是否相同。 String中equals()方法的实现为什么比Object中的equals()更复杂?- 因为
String#equals()需要比较字符串的字符序列,而不仅仅是内存地址,因此实现中需要更多的逻辑来确保内容相等。
通过以上的详细解释,你不仅能够理解 String#equals() 和 Object#equals() 之间的区别,还能在面试中清晰地表达它们的实现和应用。