一、字符串创建的两种方式
1. 字面量直接赋值
java
String s1 = "a";
- 过程 :
- JVM 检查字符串常量池中是否存在
"a"
。 - 若存在,直接返回常量池中的引用。
- 若不存在,在常量池中创建
"a"
,返回其引用。
- JVM 检查字符串常量池中是否存在
- 特点 :
- 所有相同字面量的变量共享同一份常量池对象。
2. 显式调用 new String()
java
String s2 = new String("a");
- 过程 :
- 检查字符串常量池:
- 若池中无
"a"
,先在池中创建"a"
。 - 若已有,直接使用池中的
"a"
。
- 若池中无
- 在堆内存中新建一个独立对象 ,内容与常量池中的
"a"
相同。 - 栈中的引用
s2
指向堆中的新对象。
- 检查字符串常量池:
- 特点 :
- 每次
new
都会在堆中生成新对象,与常量池无关。
- 每次
2. 内存示意图
栈内存 堆内存 字符串常量池
+------+ +----------------+ +-----+
| s1 | ------> | | | "a" |
+------+ +----------------+ +-----+
| s2 | ------> | String对象"a" |
+------+ +----------------+
s1
直接指向常量池中的"a"
。s2
指向堆中的独立对象,堆对象与常量池中的"a"
无直接关联。
四、字符串拼接的内存行为
1. 编译期优化(纯字面量拼接)
java
String s3 = "a" + "b"; // 编译后等价于 String s3 = "ab";
- 过程 :
- 编译器直接合并为
"ab"
,存入字符串常量池。
- 编译器直接合并为
2. 运行时拼接(含变量)
java
String s1 = "a";
String s2 = s1 + "b";
- 过程 :
- 运行时通过
StringBuilder
拼接,生成新字符串"ab"
。 - 结果存放在堆内存中(非常量池)。
- 运行时通过
intern()
1. 作用
- 将堆中的字符串对象尝试放入常量池 :
- 若常量池中已有相同内容,返回池中对象的引用。
- 若池中无此内容,将堆中对象的引用存入池中(JDK 7+),后续复用。
2. 示例
java
String s4 = new String("a").intern();
String s5 = "a";
System.out.println(s4 == s5); // true(均指向常量池)