Java String文字池和字符串对象

use*_*323 11 java string

我知道JVM维护一个字符串文字池来提高性能并维护JVM内存,并了解到字符串文字是在字符串池中维护的.但我想澄清与堆上创建的字符串池和字符串对象相关的内容.

如果我的解释错误,请纠正我.

String s = "abc";
Run Code Online (Sandbox Code Playgroud)

如果执行上面的行,如果池中不存在"abc"字符串文字,则将其添加到字符串池中.并且在堆上创建字符串对象,引用s将指向池中的文字.

问题:

  1. 这个代码每次执行时都会在堆上创建字符串对象吗?
  2. 字符串文字池是仅维护字符串文字还是维护字符串对象?
  3. JVM何时决定是否需要将字符串文字添加到字符串池中?它是在编译时还是运行时决定的?

如果它指向池中的字符串文字,我不确定在哪里创建字符串对象.

谢谢.

Thi*_*ilo 5

没有"文字池".Interned Strings只是普通的堆对象.它们最终可能会进入PermGen,但即便如此,它们最终也可能被垃圾收集.

类文件有一个常量池,它包含类中使用的字符串文字.加载类时,会根据该数据创建String对象,这可能与String #intern的做法非常相似.

这个代码每次执行时都会在堆上创建字符串对象吗?

不会.将有一个正在重用的String对象.它已在加载类时创建.

字符串文字池是仅维护字符串文字还是维护字符串对象?

你也可以实习弦乐.我认为他们的待遇大致相同.

JVM何时决定是否需要将字符串文字添加到字符串池中?它是在编译时还是运行时决定的?

文字总是"汇集".其他字符串需要在其上调用"实习生".所以在某种程度上,决定是在编译时做出的.


Mar*_*ers 1

我认为您缺少一些基本的东西:实习字符串池包含 String 对象。文字并不是某种特殊的对象;而是某种特殊的对象。在运行时它们只是另一个 String 对象。

另外,您可以使用任何您想要的字符串String.intern();它不一定源自文字。

所以关于你的问题:

  1. 不,类加载时会分配一个 String 对象。
  2. 它不维护任何文字,而是保留的 String 对象。通常,它们来自文字,但实际上它可以是任何编译时常量表达式(String constant = "abc" + "def"在运行时会产生一个字符串对象“abcdef”)。
  3. 它们被编译到类文件中。因此它们是在编译时决定的,但显然对象本身是在运行时创建的。