← 返回首页

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")。