← 返回首页
1.
2.
Java中 == 与 equals 有什么区别?
这是 Java 中最经典的基础面试题之一。它们的核心区别可以用一句话概括:
==比较的是"地址"(引用是否指向同一个对象),equals()比较的是"内容"(对象的值是否相等)。
1. == 的行为
== 是一个运算符,它的行为取决于操作数的类型:
- 基本数据类型(byte、short、int、long、float、double、char、boolean):直接比较值是否相等。
- 引用数据类型(类、接口、数组等):比较的是两个引用是否指向同一个对象(即内存地址是否相同)。
// 基本类型:比较值
int a = 10;
int b = 10;
System.out.println(a == b); // true
// 引用类型:比较地址
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false,两个不同的对象,地址不同
2. equals() 的行为
equals() 是 Object 类中的一个方法,所有类都继承自 Object,因此所有对象都有 equals() 方法。
- 默认实现(Object 类中的源码):直接返回
==的比较结果,即比较地址。 重写后的实现:很多类(如String、Integer、ArrayList等)都重写了equals(),使其比较对象的内容而非地址。
3. 经典案例对比
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = s1;
System.out.println(s1 == s2); // false,两个不同的对象
System.out.println(s1 == s3); // true,s3 和 s1 指向同一个对象
System.out.println(s1.equals(s2)); // true,内容相同
System.out.println(s1.equals(s3)); // true,内容相同
4. 字符串常量池的干扰
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true!因为字符串常量池的优化
System.out.println(s1.equals(s2)); // true
这里 s1 == s2 为 true,是因为 Java 为了节省内存,将字符串字面量放入了字符串常量池中,两个 "hello" 实际上指向的是同一个对象。这也是很多人混淆 == 和 equals() 的原因。
5. 总结对比表
| 对比维度 | == |
equals() |
|---|---|---|
| 本质 | 运算符 | 方法 |
| 基本类型 | 比较值 | 不适用(基本类型没有方法) |
| 引用类型(默认) | 比较内存地址 | 默认也是比较内存地址 |
| 引用类型(重写后) | 仍然比较内存地址 | 通常比较对象内容 |
| 能否被重写 | 不能 | 能 |
| 典型用途 | 判断两个引用是否指向同一对象 | 判断两个对象的逻辑值是否相等 |
最佳实践
- 比较基本类型的值,用
==。 - 比较对象的内容是否相等,用
equals()。 - 比较对象是否是同一个实例,用
==。 - 使用
equals()时,注意空指针风险,建议将确定不为null的字符串放在前面,例如"hello".equals(str)而不是str.equals("hello")。