重点
主要涉及字符串常量池 和用new关键字创建对象的特点
概述
在 Java 中,当你执行 String s = new String("abc")
时,实际上执行一下步骤:
-
字符串常量池(String Literal Pool):
- 字符串
"abc"
是一个字符串字面量,它首先会在字符串常量池中查找是否存在相同的字符串。如果不存在,则会在字符串常量池中创建一个新的字符串对象"abc"
。
- 字符串
-
使用
new
创建新对象:- 接下来的
new String("abc")
会创建一个新的String
对象,这个对象的内容是"abc"
,但这个新的对象并不是在字符串常量池中创建的,而是在堆上创建的。
- 接下来的
因此,在执行 String s = new String("abc")
时,总共创建了 两个对象:
- 在字符串常量池中的
"abc"
对象。 - 在堆上的新的
String
对象。
详细的内存分配情况
-
字符串常量池中的
"abc"
:- 如果之前没有
"abc"
这个字符串存在于字符串常量池中,那么第一次执行new String("abc")
时会在字符串常量池中创建一个"abc"
的实例。如果"abc"
已经存在,则不会重复创建。
- 如果之前没有
-
堆上的
String
对象:- 不管
"abc"
是否已经存在于字符串常量池中,new String("abc")
都会在堆上创建一个新的String
对象。
- 不管
示例代码
下面是一个简单的示例代码,演示了上述过程:
1public class StringCreationExample {
2 public static void main(String[] args) {
3 String s1 = "abc";
4 String s2 = new String("abc");
5
6 System.out.println(s1 == s2); // 输出 false
7 System.out.println(s1 == s2.intern()); // 输出 true
8 }
9}
s1
:直接通过字符串字面量创建,指向字符串常量池中的"abc"
。
s2
:通过new String("abc")
创建,指向堆上的新String
对象。
s2.intern()
:- 调用
intern()
方法会使s2
引用指向字符串常量池中的"abc"
,如果"abc"
已经存在于字符串常量池中,则返回已有的引用;否则,先创建"abc"
并返回该引用。
总结
- 当你使用
new String("abc")
时,创建了两个String
对象:一个在字符串常量池中(如果"abc"
不存在的话),另一个在堆上。 - 如果你多次执行
new String("abc")
,堆上的String
对象会被多次创建,但字符串常量池中的"abc"
只会在首次创建时创建一次。
理解这一点对于理解 Java 中的内存管理非常重要,尤其是在处理大量字符串时,了解这些细节有助于优化内存使用和提高程序性能。