字符串池存储文字还是对象?

Does string pool store literals or objects?

Whosebug 充满了与不同类型的 String 初始化相关的问题。我了解 String s = "word"String s = new String("word") 有何不同。所以没必要'touch'那个话题。

我注意到不同的人提到字符串池存储 constants/objects/literals.

常量 是可以理解的,因为它们是最终的,所以它们总是 'stay' 在那里。是的,SCP.

中也没有存储重复项

但我无法理解 SCP 是否存储 objectsliterals。它们是完全不同的概念。 对象一个实体,而文字只是一个值.那么这个问题的正确答案是什么。 SCP 存储的是 objects 还是 literals?我知道不能两者兼得 :)

严格来说,“文字”不是一个值;它是一种句法形式。 Java 中的字符串文字是一个双引号,后跟一些 non-double-quote(或转义双引号)字符,以另一个双引号结尾。 “文字值”是从 source-code 文字创建的值,而不是 a.concat(b) 等评估值。核心区别在于字面值可以在编译时识别,而评估值只能在执行期间获知。这允许编译器将文字值存储在编译后的字节码中。 (由于编译器在编译时也知道由字面值初始化的常量,因此也可以在编译时计算仅使用常量的求值。)

在口语中,可以将文字值称为“文字”,但这可能是您混淆的根源 - 值就是一个值,无论其来源是文字还是评估。

I know it can't be both

文字值和评估值之间的区别不同于对象值和原始值之间的区别。 "foo" 是一个文字字符串值(并且由于字符串是对象,它也是一个对象)。 3 是一个文字原始(整数)值。如果 x 当前为 7,则 18 - x 的计算结果为 non-literal 原始值 11。如果 y 当前为 "world!",则 "Hello, " + y 的计算结果为 non-literal、non-primitive 值 "Hello, world!".

文字 是由" 分隔的源代码 的一大块。例如,在下面的源代码行中:

String s = "Hello World";

"Hello World" 是字符串文字。

对象 是一个有用的抽象,用于有意义的内存位,其中的数据(当组合在一起时)代表某种东西,无论它是 CarPerson, 或 String.

字符串池存储 String 个对象而不是 String 个文字,仅仅是因为 字符串池不存储源代码

您可能会听到人们说“字符串池存储字符串文字”。他们(可能)并不意味着字符串池以某种方式在其中包含源代码 "Hello World"。它们(可能)意味着源代码中由字符串文字表示的所有 String 都将放入字符串池中。事实上,源代码中由常量表达式生成的 Strings 也会自动添加到字符串池中。

问得好。通过 String::intern() 的实现方式可以找到答案。来自 javadoc:

* When the intern method is invoked, if the pool already contains a
 * string equal to this {@code String} object as determined by
 * the {@link #equals(Object)} method, then the string from the pool is
 * returned. Otherwise, this {@code String} object is added to the
 * pool and a reference to this {@code String} object is returned.
 * <p>

因此字符串池存储字符串对象。

我们可以打开源代码来确认答案。 String::intern() 是一种本地方法,它在 StringTable::intern()、symbolTable.hpp

中定义
oop StringTable::intern(Handle string_or_null, jchar* name,
                    int len, TRAPS) {
  unsigned int hashValue = hash_string(name, len);
  int index = the_table()->hash_to_index(hashValue);
  oop found_string = the_table()->lookup(index, name, len, hashValue);

  // Found
  if (found_string != NULL) {
    ensure_string_alive(found_string);
    return found_string;
  }

  ... ...

  Handle string;
  // try to reuse the string if possible
  if (!string_or_null.is_null()) {
    string = string_or_null;
  } else {
    string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
  }

... ...

  // Grab the StringTable_lock before getting the_table() because it could
  // change at safepoint.
  oop added_or_found;
  {
    MutexLocker ml(StringTable_lock, THREAD);
    // Otherwise, add to symbol to table
    added_or_found = the_table()->basic_add(index, string, name, len,
                              hashValue, CHECK_NULL);
  }

  ensure_string_alive(added_or_found);

  return added_or_found;
}

http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/f3108e56b502/src/share/vm/classfile/symbolTable.cpp