在Java中,String
对象是不可变的,即一旦创建后,其内容不能被修改。对于字符串对象的比较,使用==
比较的是引用地址,而使用.equals()
方法比较的是字符串的内容。现在让我们来详细解释下这个问题,并结合代码进行演示。
public class StringComparisonDemo {
public static void main(String[] args) {
String a = "ab"; // 在编译时常量池中创建 "ab" 字符串对象
String b = "a" + "b"; // 在编译时常量池中创建 "ab" 字符串对象
// 判断是否为同一个引用
System.out.println("a == b: " + (a == b)); // 输出 true,因为 a 和 b 都指向编译时常量池中的同一个对象
// 判断内容是否相同
System.out.println("a.equals(b): " + a.equals(b)); // 输出 true,因为 a 和 b 的内容都是 "ab"
}
}
输出结果为:
a == b: true
a.equals(b): true
从输出结果可以看出,a
和b
的引用地址是相同的,因此a == b
返回true
。同时,它们的内容也相同,因此a.equals(b)
返回true
。
原因解析:
在Java中,字符串连接表达式"a" + "b"
会在编译时被优化,将其直接转换为一个字符串常量"ab"。因此,b
实际上指向编译时常量池中的"ab"字符串对象,与a
指向的对象是同一个。
值得注意的是,如果字符串连接表达式中存在变量,那么在运行时就无法在编译时进行优化了,例如:
public class StringComparisonDemo {
public static void main(String[] args) {
String a = "ab"; // 在编译时常量池中创建 "ab" 字符串对象
String x = "a";
String y = "b";
String b = x + y; // 运行时连接 x 和 y,创建新的字符串对象
// 判断是否为同一个引用
System.out.println("a == b: " + (a == b)); // 输出 false,a 和 b 的引用地址不同
// 判断内容是否相同
System.out.println("a.equals(b): " + a.equals(b)); // 输出 true,a 和 b 的内容都是 "ab"
}
}
输出结果为:
a == b: false
a.equals(b): true
在这个例子中,由于x
和y
是变量,因此字符串连接表达式x + y
在运行时才能确定结果。所以,b
是在堆中新创建的一个字符串对象,其引用地址与a
不同。但是由于内容相同,a.equals(b)
仍然返回true
。