我知道JVM维护一个字符串文字池来提高性能并维护JVM内存,并了解到字符串文字是在字符串池中维护的 . 但我想澄清与堆上创建的字符串池和字符串对象相关的内容 .
如果我的解释错误,请纠正我 .
String s = "abc";
如果执行上面的行,则如果池中不存在"abc"字符串文字,则将其添加到字符串池中 . 并且在堆上创建字符串对象,引用 s
将指向池中的文字 .
问题:
-
这段代码每次执行时都会在堆上创建字符串对象吗?
-
字符串文字池是仅维护字符串文字还是维护字符串对象?
-
JVM何时决定是否需要将字符串文字添加到字符串池中?它是在编译时还是运行时决定的?
如果它指向池中的字符串文字,我不确定在哪里创建字符串对象 .
谢谢 .
4 回答
我认为缺少's something fundamental you':实习字符串池只包含String对象 . 文字不是某种特殊的对象;在运行时,它们只是另一个String对象 .
另外,你可以使用
String.intern()
实习你想要的任何字符串;它不一定来自文字 .所以关于你的问题:
不,在加载类时会分配一个String对象 .
它不维护任何文字,而是维护实体的String对象 . 通常,那些来自文字,但实际上它可以是任何编译时常量表达式(
String constant = "abc" + "def"
将在运行时产生一个String对象"abcdef") .它们被编译到类文件中 . 所以它们是在编译时决定的,但显然对象本身是在运行时创建的 .
没有“文字池” . Interned Strings只是普通的堆对象 . 它们最终可能会进入PermGen,但即便如此,它们最终也可能被垃圾收集 .
类文件有一个常量池,它包含类中使用的字符串文字 . 加载类时,会根据该数据创建String对象,这可能与String #intern的做法非常相似 .
不会 . 将有一个正在重用的String对象 . 它已在加载类时创建 .
你也可以实习弦乐 . 我认为他们的待遇大致相同 .
文字总是“汇集” . 其他字符串需要在其上调用“实习生” . 所以在某种程度上,决定是在编译时做出的 .
引用String.intern()的文件(强调我的)
因此,
仅为每个唯一的实习字符串创建一个对象 . 所有引用都共享此不可变对象 .
没有'Literal Objects' . 转换后的文字字符串表达式存储为常规
String
对象 . 此外,池包含所有实际字符串对象 . 隐式(通过使用字符串文字表达式)和显式(通过在String
对象上调用.intern()
) .我不确定 .
这个代码每次执行时都会在堆上创建字符串对象吗?
不 . 一旦在文字池中创建 . 同样一次又一次地提到 .
字符串文字池是仅维护字符串文字还是维护字符串对象?
所有都只是对象,但是通过赋值创建的对象放在池中,其中通过
new
运算符创建的对象放在堆上 .JVM何时决定是否需要将字符串文字添加到字符串池中?它是在编译时还是运行时决定的?
每当JVM遇到类似的表达式时
并且结果字符串(在这种情况下为
str
)不是池,然后在所有这些情况下,它在池中添加新字符串 . 这个过程在运行时发生 .查看this链接 .