核心要点
一句话总结:String.equals() 方法用于比较两个字符串的内容是否完全相同,而不是比较它们的内存地址。

为什么需要 equals() 方法?
在 Java 中, 运算符有两个主要用途:
-
基本数据类型:比较它们的值是否相等。
int a = 5; int b = 5; a == b;// 结果为true
-
引用数据类型(如
String,Object等):比较它们的内存地址(引用)是否相等,即它们是否指向同一个对象。String s1 = new String("hello");String s2 = new String("hello");s1 == s2;// 结果为false,因为s1和s2是两个在内存中独立创建的String对象,地址不同。
对于字符串,我们通常关心的是它们的内容(即 "hello")是否一样,而不是它们是不是同一个对象。 无法满足这个需求,String.equals() 方法应运而生。

equals() 方法的详细用法
String 类重写了从 Object 类继承来的 equals() 方法,使其专门用于比较字符串内容。
方法签名
public boolean equals(Object anObject)
工作原理
equals() 方法会逐个字符地比较两个字符串的字符序列,如果所有字符都相同,并且两个字符串的长度也相同,则返回 true;否则返回 false。
示例
public class StringEqualsExample {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
String s4 = "world";
// 1. 字符串字面量比较 (JVM 优化)
// 在 Java 中,字符串字面量会被放入字符串常量池,如果两个字符串内容相同,
// JVM 可能会让它们指向同一个对象。
System.out.println("s1 == s2: " + (s1 == s2)); // true (通常情况下)
System.out.println("s1.equals(s2): " + s1.equals(s2)); // true
System.out.println("--------------------");
// 2. 字符串字面量与 new String() 比较
// new String() 总是在堆内存中创建一个新的对象,即使内容相同。
System.out.println("s1 == s3: " + (s1 == s3)); // false (地址不同)
System.out.println("s1.equals(s3): " + s1.equals(s3)); // true (内容相同)
System.out.println("--------------------");
// 3. 内容不同的字符串比较
System.out.println("s1 == s4: " + (s1 == s4)); // false
System.out.println("s1.equals(s4): " + s1.equals(s4)); // false
System.out.println("--------------------");
// 4. 比较一个字符串与 null
String s5 = null;
// System.out.println(s5.equals(s1)); // 这会抛出 NullPointerException
// 正确的比较方式是:将常量放在前面,避免 NPE
System.out.println("s1.equals(s5): " + "hello".equals(s5)); // false
}
}
equals() 的一个重要变体:equalsIgnoreCase()
我们不关心字母的大小写,只关心字母是否相同,这时可以使用 equalsIgnoreCase() 方法。
public class StringEqualsIgnoreCaseExample {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "hello";
String s3 = "HELLO";
System.out.println("s1.equals(s2): " + s1.equals(s2)); // false (区分大小写)
System.out.println("s1.equalsIgnoreCase(s2): " + s1.equalsIgnoreCase(s2)); // true (不区分大小写)
System.out.println("s1.equalsIgnoreCase(s3): " + s1.equalsIgnoreCase(s3)); // true
}
}
equals() 与 的最佳实践和陷阱
陷阱 1:混淆 和 equals()
这是最常见的初学者错误,记住这个黄金法则:
- 想比较对象的内容(比如字符串的值)?用
equals()。 - 想判断两个变量是不是指向同一个对象(地址相同)?用 。
陷阱 2:NullPointerException (空指针异常)
当你调用一个变量的 equals() 方法时,如果这个变量是 null,程序就会崩溃。
String s = null;
s.equals("some string"); // 抛出 NullPointerException
安全的比较方式
为了避免 NullPointerException,有一个非常推荐的写法:将常量字符串放在 equals() 方法的左侧。
// 安全的方式
"some string".equals(s); // s 是 null,这个表达式会返回 false,而不会抛出异常
// 危险的方式
s.equals("some string"); // s 是 null,程序崩溃
更现代的写法:Objects.equals()
从 Java 7 开始,java.util.Objects 类提供了一个更安全的 equals() 方法,它会自动处理 null 值,避免了上述的陷阱。
import java.util.Objects;
public class SafeEqualsExample {
public static void main(String[] args) {
String s1 = "hello";
String s2 = null;
// 使用 Objects.equals()
// 它内部逻辑类似: (a == b) || (a != null && a.equals(b))
boolean result = Objects.equals(s1, s2);
System.out.println("Objects.equals(s1, s2): " + result); // 输出 false,不会抛出异常
String s3 = null;
result = Objects.equals(s3, s2);
System.out.println("Objects.equals(s3, s2): " + result); // 输出 true
}
}
在比较可能为 null 的对象时,强烈推荐使用 Objects.equals()。
| 方法 | 描述 | 示例 | 结果 |
|---|---|---|---|
| 比较两个引用是否指向同一个内存地址。 | s1 == s2 |
true / false |
|
equals() |
比较两个字符串的是否完全相同(区分大小写)。 | s1.equals(s2) |
true / false |
equalsIgnoreCase() |
比较两个字符串的是否相同(不区分大小写)。 | s1.equalsIgnoreCase(s2) |
true / false |
Objects.equals() |
安全的 equals() 方法,能自动处理 null 值,避免 NPE。 |
Objects.equals(s1, s2) |
true / false |
记住这些核心概念,你就能在 Java 编程中正确、安全地处理字符串比较了。
