在Java中,当我们在终端上打印一个字符串字面量时,这个字符串字面量是否也存储在字符串池中?

In Java, when we print a string literal on to the terminal, does this string literal also be stored in the string pool?

我知道当我们将一个字符串文字初始化为一个变量时,这个文字将被 JVM 存储在字符串池中。考虑下面的代码。

System.out.println("This is a string literal");

即使我不将其初始化为变量,引号内的字符串字面量是否也存储在字符串池中?

我会在这个答案的开头说,在深入了解 Java 字符串池方面几乎没有 实用 用途。从实际的角度来看,你只需要记住两件事:

  • 不要使用 == 来比较字符串。使用 equalscompareTo 或等效方法。

  • 不要在代码中使用显式 String.intern 调用。如果您想避免重复字符串的潜在问题,请启用现代 Java GC 中提供的字符串重复数据删除功能。


I am aware that when we initialize a string literal either using the 'new' keyword or not, this literal will be stored in the string pool by the JVM.

这是乱码。

首先,您没有“初始化”字符串文字。你初始化一个变量。

String hi = "hello";  // This initializes the variable `hi`.

其次,您通常不会/不应将字符串文字与 new.

一起使用
String hi = new String("hello");  // This is bad.  You should write this as above.

使用 new 创建字符串的正常用例是这样的:

String hi = new String(arrayOfCharacters, offset, count);

实际上,对应于字符串文字的 String 对象的创建和驻留发生在第一次在表达式中使用该文字或更早的时候。确切的细节(即何时发生)未指定并且(我理解)版本相关。

第一次使用可能是在变量初始化中,也可能是在其他地方;例如方法调用。


所以对于你的问题:

Consider the piece of code below:

System.out.println("This is a string literal");

Does the string literal within the quotes also be stored in the string pool even if I do not initialize it?

是的,确实如此。如果那是第一次使用文字,上面的代码可能会触发这种情况发生。但这可能以前发生过;例如如果上面的代码是 运行 更早的话。


作为后续,您问:

Why does the String Pool collect string literals which are not stored in a variable and just displayed in the console?

因为 JLS 3.10.5 要求 与字符串文字对应的 String 对象被驻留:

"Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern (§12.5)."

你问:

The Presence of the String Pool help optimize the program. By storing literals as such (which is actually not required because it is just to be displayed in the console), isn't it the case that it goes against its whole purpose (which is optimization)?

interning和string pool最初的想法是为了节省内存。这在 25 年前设计和最初指定 Java 语言时是有道理的。如今,即使是低端 Android phone 也有 1GB 的 RAM,为了节省几千字节而对字符串文字进行驻留有点毫无意义。除了 JLS 说这 必须 发生。

但答案是否定的,这并不违背(最初)的目的。本声明:

System.out.println("This is a string literal");

可以执行多次。您不希望/不需要在每次执行时都为文字创建一个新的 String 对象。问题是 JVM 不知道会发生什么。

无论如何,实习必须发生,因为规范就是这么说的。