在Java中,当你执行 String str = new String("Hello, World!");
这行代码时,实际上发生了几件事情:
-
字符串常量池中的字符串 :首先,Java会检查字符串字面量
"Hello, World!"
是否已经在字符串常量池(String Constant Pool)中存在。字符串常量池是Java堆内存中的一个特殊区域,用于存储字符串字面量。如果常量池中已经存在该字符串,那么它不会被再次创建。但是,在这个例子中,我们假设这是第一次遇到这个字符串字面量,所以Java会在字符串常量池中创建一个新的字符串对象"Hello, World!"
。 -
使用
new
创建新的对象 :然后,new String("Hello, World!")
调用String
类的构造函数来创建一个新的String
对象。这个新的对象是在堆内存中分配的,与字符串常量池中的字符串是不同的对象,尽管它们的内容是相同的。 -
引用赋值 :最后,
str
变量被赋值为新创建的String
对象的引用,而不是字符串常量池中的字符串的引用。
这里的关键点是,虽然两个字符串对象的内容相同,但是它们是两个不同的对象,分别位于不同的内存区域(一个是字符串常量池,另一个是堆内存)。
为了证明这一点,你可以使用 ==
运算符和 equals()
方法来比较这两个字符串:
java
String str1 = "Hello, World!"; // 直接引用字符串常量池中的字符串
String str2 = new String("Hello, World!"); // 使用new创建新的字符串对象
System.out.println(str1 == str2); // 输出false,因为它们是不同的对象
System.out.println(str1.equals(str2)); // 输出true,因为它们的内容相同
str1 == str2返回
false,因为
str1和
str2引用的是不同的对象。而
str1.equals(str2)返回
true,因为
equals()` 方法比较的是字符串的内容,而不是它们的引用。