跳到主要内容
Java 中 String 对象创建机制解析 | 极客日志
Java java
Java 中 String 对象创建机制解析 Java String 对象创建涉及字符串驻留池、堆内存分配及常量折叠机制。使用双引号赋值时,若常量池存在则复用,否则新建;使用 new 关键字则在堆中强制创建新对象。字符串拼接在编译期若均为字面量会进行常量折叠,合并为一个对象;若包含变量或 new 对象,则通过 StringBuilder 运行时拼接,生成额外对象。掌握这些机制有助于优化内存使用,避免不必要的对象创建。
赛博行者 发布于 2025/2/3 更新于 2026/9/4 63 浏览在开始之前,我们先了解一下字符串驻留 的概念。
当同时创建多个相同的字符串字面量时,只有一个字符串常量被存储在运行时常量池中。
例如:
String a = "abc" ;
String b = "abc" ;
此时虽然创建了两次 String 引用,但在运行时常量池中只有一个 "abc"。对于 String c = new String("abc"),可以通过 c.intern() 获取该字符串在运行时常量池中的引用对象,因此:
String a = new String ("abc" );
String b = new String ("abc" );
System.out.println(a == b);
System.out.println(a.intern() == b.intern());
1. String a="abc"与 String b=new String("abc")一样吗?
首先是不一样的,也不是语法糖。我们看以下代码:
public static void main (String[] args) {
String a = "abc" ;
String b = "abc" ;
String c = new String ( );
( );
.length();
}
"Hello world"
String
d
=
new
String
"abc"
int
length
=
"abc"
从字节码分析可以看到,String a = "abc" 只创建了一个对象(即 "abc",位于运行时常量池)。而 String a = new String("abc") 会创建额外的对象 。使用 new 关键字意味着在堆内存中也创建了一个对象。
a、b 两个对象都是通过 ldc 指令将常量 "abc" 加载进操作数栈的,所以 a == b 为 true。然而 String d = new String("abc") 会在堆中新建一个 String 对象,所以 d == b 为 false。
通常创建 String 对象时,推荐使用双引号方式,因为 new 的方式会额外创建一个对象。
2. String a="abc"要创建几个对象? 通过上面的解释可知,String a = "abc" 会创建一个对象(在运行时常量池),而 String a = new String("abc") 会创建两个对象(一个在运行时常量池的 "abc",一个在堆里面)。需要注意的是,这是在两者不同时出现的情况下。
3. String a="abc"; String b=new String("abc") 又要创建几个对象? 理解上述内容后便容易解答。当 String a = "abc" 与 String b = new String("abc") 同时出现时,总共会创建 2 个对象。
首先 String a = "abc" 在运行时常量池中创建了一个对象。当执行 String b = new String("abc") 时,由于运行时常量池中已存在对象 "abc",则不需要在常量池中新建,只需在堆中创建一个对象即可。
4. String a="abc"; String b="abc"; 那么 a==b 吗? 结果为 true。正如前文所述,a 与 b 都指向了运行时常量池中的 "abc"。
5. String a="hello"+"world", 创建几个对象?String b="helloworld", a==b 吗? 这里涉及常量折叠 概念。这是在早期编译阶段的一种优化。例如:
经过常量折叠后,1、+、2 变成了字面量 3,所以在代码中定义 int a = 1 + 2 并不比 int a = 3 增加程序运行期的运算量。
相应的,"hello"、"world" 也是常量,经过常量折叠后与 String b = "helloworld" 无异。所以 a == b 为 true 。因此 String a = "hello" + "world" 也只会产生一个对象 。
public class Main {
public static void main (String[] args) {
String a = "helloWorld" ;
String b = "hello" + "World" ;
System.out.println(a == b);
}
}
使用 javap -verbose Main 查看,只有合并后的常量,而没有单独的 hello 和 world。且 ldc 加载的常量索引相同,说明 String a = "helloworld" 与 String b = "hello" + "world" 没有区别。
String c=new String("hello"+"world") 创建了几个对象? 由于经过常量折叠 ,"hello" + "world" 与 "helloworld" 没有区别,所以:
String c = new String ("hello" + "world" );
String c = new String ("helloworld" );
效果一致,String c = new String("hello" + "world") 也只产生两个对象 (一个常量池,一个堆)。
6. 下面程序创建几个对象?特别注意 String b=new String("hello")+new String("world") 产生几个对象? String a = "hello" + "world" ;
String b = new String ("hello" ) + new String ("world" );
对于 String a = "hello" + "world",肯定只创建一个对象 。
而对于 String b = new String("hello") + new String("world"),会产生 7 个对象:
"hello" 与 "world" 两个在运行时常量池的对象。
new String("hello") 与 new String("world") 两个在堆中的对象。
Java 8 中字符串拼接使用 StringBuilder 实现,需要创建一个 StringBuilder 对象。
StringBuilder 内部有一个 char[] 数组,数组本身也是一个对象。
调用 StringBuilder 对象的 toString() 方法时,又会 new 一个 String 对象。
查看 StringBuilder.append(String) 源码:
@Override
public StringBuilder append (String str) {
super .append(str);
return this ;
}
它调用了父类方法 super.append(str):
public AbstractStringBuilder append (String str) {
if (str == null ) return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0 , len, value, count);
count += len;
return this ;
}
看到 value 了吗?它是一个 char[] 数组,数组也算对象:
至此第 6 个对象找到了。再看第 7 个对象,随后调用 toString() 方法:
@Override
public String toString () {
return new String (value, 0 , count);
}
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online