Java 堆行为中的新 String 和新 StringBuilder

Java new String and new StringBuilder in heap behavior

  1. 字符串池是否驻留在堆上?如果是,字符串文字是否符合垃圾回收条件?

使用new String("abc")时,我们知道它在堆上创建一个对象,并将String字面量放入String池中。所以我的第二个问题是:

  1. new StringBuilder("abc") 的行为方式是否与 new String("abc") 相同?如果是,StringBuilder如何操作String池中的String文字?

首先,是的,字符串池和它包含的字符串都在堆上。一旦字符串文字在字符串池中,它就永远不会从中删除。因此,在程序终止之前,字符串池中的所有字符串文字都是可访问的,因此不符合垃圾收集的条件。 (通过其他方式添加到字符串池的字符串可能符合垃圾回收条件。)

如果我们通过 new String("abc") 创建一个新的字符串对象,则会发生两件事:首先,由于字符串文字 "abc",将创建一个内容为 "abc" 的新字符串对象添加到字符串池(如果它不存在)。然后,由于 new String(...) 构造函数,创建了一个新的 String 对象,它是字符串文字的副本。这个新字符串没有放在字符串池中。因此,new String("abc") == "abc" 不成立。

代码 new StringBuilder("abc") 做的事情与 new String("abc") 不同,因为它创建的是 StringBuilder 对象而不是 String。但是,由于字符串文字 "abc",它确实确保内容为 "abc" 的字符串对象在字符串池中。

您混淆了编译时间、加载时间和运行时间。

在 class 加载时将字符串文字添加到常量池中。在 class 代码中的任何地方只需 提及 就足够了;您甚至不必执行 class.

中的任何代码行

另一方面,表达式 new String("literal") 每次被计算时都会产生一个新的 String 实例。该实例与常量池中的实例不同,并且具有字符串值的副本。

StringBuilder 在这方面与 String 的行为完全相同:它使用字符串文字值的副本进行初始化。