我知道JVM维护一个字符串文字池来提高性能并维护JVM内存,并了解到字符串文字是在字符串池中维护的。但我想澄清一下与堆上创建的字符串池和字符串对象有关的内容。
如果我的解释错误,请纠正我。
String s = "abc";
如果执行上面的行,如果池中不存在“abc”字符串文字,则将其添加到字符串池中。并且在堆上创建字符串对象,引用s
将指向池中的文字。
问题:
如果它指向池中的字符串文字,我不确定在哪里创建字符串对象。
感谢。
答案 0 :(得分:5)
没有“文字池”。 Interned Strings只是普通的堆对象。它们最终可能会进入PermGen,但即便如此,它们最终也可能被垃圾收集。
类文件有一个常量池,它包含类中使用的字符串文字。加载类时,会根据该数据创建String对象,这可能与String #intern的内容非常相似。
这段代码每次执行时都会在堆上创建字符串对象吗?
没有。将有一个正在重用的String对象。它是在加载类时创建的。
字符串文字池是仅维护字符串文字还是维护字符串对象?
你也可以实习字符串。我认为他们的待遇大致相同。
JVM何时决定是否需要将字符串文字添加到字符串池中?它是在编译时还是运行时决定的?
文字总是“汇集”。其他字符串需要在其上调用“实习生”。所以在某种程度上,决定是在编译时做出的。
答案 1 :(得分:4)
引用String.intern()的文档(强调我的)
所有文字字符串和字符串值常量表达式都是 实习。字符串文字在Java语言的§3.10.5中定义 说明书
一个字符串池,最初是空的,由私有维护 class String。
调用实习方法时,如果池已包含 字符串等于此字符串对象由equals(Object)确定 方法,然后返回池中的字符串。否则,这个 String对象被添加到池中以及对此String的引用 返回对象。
<小时/> 因此,
此代码是否每次都在堆上创建字符串对象 执行?
每个唯一的实习字符串只创建一个对象。所有引用都共享此不可变对象。
字符串文字池是仅维护字符串文字还是维护字符串对象?
没有'文字对象'。转换后的文字字符串表达式存储为常规String
对象。此外,池包含所有实体字符串对象。隐式(通过使用字符串文字表达式)和显式(通过在.intern()
对象上调用String
)。
JVM何时决定需要将字符串文字添加到字符串中 池?它是在编译时还是运行时决定的?
我不确定。
答案 2 :(得分:1)
我认为你缺少一些基本的东西:实习字符串池只有包含String对象。文字不是某种特殊的对象;在运行时,它们只是另一个String对象。
另外,您可以使用String.intern()
实习所需的任何字符串;它不一定来自文字。
关于你的问题:
String constant = "abc" + "def"
将在运行时导致一个String对象“abcdef”。答案 3 :(得分:1)
这段代码每次执行时都会在堆上创建字符串对象吗?
不。一旦在文字池中创建。同样一次又一次地提到。
字符串文字池是仅维护字符串文字还是维护字符串对象?
所有都只是对象,但通过赋值创建的对象放在池中,而通过new
运算符创建的对象放在堆上。
JVM何时决定是否需要将字符串文字添加到字符串池中?它是在编译时还是运行时决定的?
每当JVM遇到类似
的表达式时String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).
并且结果字符串(在这种情况下为str
)不是池,然后在所有这些情况下,它在池中添加新字符串。这个过程在运行时发生。
查看this链接。