Java中字符串字面量与String对象的内存关联关系是什么?
Java字符串常量池与堆中String对象的关联解析
Great question! Let's break down the relationship between s1 and s2 from Java's memory management perspective, step by step:
1. 当执行String s1 = "ABC";时
JVM会先检查字符串常量池(属于方法区的一部分)中是否已经存在值为"ABC"的字符串对象:
- 如果不存在,就会在常量池中创建一个
"ABC"字符串对象; - 如果已经存在(比如之前有其他字面量定义过),直接复用这个对象。
最终变量s1的引用直接指向常量池中的"ABC"对象。
2. 当执行String s2 = new String("ABC");时
这行代码会触发两个关键操作:
- 首先,JVM依然会检查字符串常量池:如果此时常量池中没有
"ABC",会先在常量池中创建这个对象(不过在你的例子里,s1已经提前创建了,所以常量池里已经有"ABC"了); - 然后,JVM会在堆内存中创建一个全新的
String对象。这个堆中的String对象并不会重新存储"ABC"的字符数据,而是引用常量池中"ABC"的底层字符数组(Java 9及以后是字节数组)。也就是说,堆里的s2对象和常量池里的"ABC"共享了核心的字符内容。
3. 直观验证
你可以通过代码验证这个关联和区别:
String s1 = "ABC"; String s2 = new String("ABC"); // 输出false:s1指向常量池,s2指向堆,引用地址不同 System.out.println(s1 == s2); // 输出true:二者的字符内容完全一致 System.out.println(s1.equals(s2)); // 输出true:s2.intern()会返回常量池中的"ABC"引用,和s1指向同一个对象 System.out.println(s1 == s2.intern());
简单总结:s2(堆中的String对象)和s1(常量池中的String对象)的关联在于,堆对象复用了常量池对象的字符数据,但二者是不同的对象实例,存储在不同的内存区域。
内容的提问来源于stack exchange,提问作者shaggy007
相关产品推荐
相关产品推荐

