字符串池是否存储文字或对象?

时间:2020-10-06 04:25:37

标签: java string object string-pool string-constant

Stackoverflow 充满了与不同类型的String初始化相关的问题。我了解String s = "word"String s = new String("word")有何不同。因此,无需“触摸”该主题。

我注意到有不同的人提到String池存储常量/对象/文字

常量是可以理解的,因为它们是最终的,因此它们总是“呆在”那里。是的,重复项也不会存储在 SCP 中。

但是我不知道 SCP 是否存储对象文字。它们是完全不同的概念。 对象实体,而文字只是一个值。那么正确的答案是什么。 SCP 是否存储对象文字?我知道不能同时都是:)

3 个答案:

答案 0 :(得分:3)

严格来说,“文字”不是值;它是一种语法形式。 Java中的String文字是双引号,后跟一些非双引号(或转义的双引号)字符,并以另一个双引号结尾。 “文字值”是根据源代码文字创建的值,而不是诸如a.concat(b)之类的评估值。核心区别在于字面值可以在编译时识别,而评估值只能在执行期间知道。这允许编译器将文字值存储在已编译的字节码内。 (由于编译器在编译时也知道由文字值初始化的常量,因此也可以在编译时计算仅使用常量的求值。)

在口语演讲中,人们可以将文字值称为“文字”,但这可能是造成混淆的原因-值就是值,无论其来源是文字还是评估。

我知道不能同时存在

文字值和评估值之间的区别与对象值和原始值之间的区别是分开的。 "foo"是文字字符串值(由于字符串是对象,因此它也是一个对象)。 3是文字原语(整数)值。如果x当前为7,则18 - x的计算结果为非文字原始值11。如果y当前为"world!",则"Hello, " + y的计算结果为非文字,非原始值"Hello, world!"

答案 1 :(得分:3)

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

String s = "Hello World";

"Hello World"是字符串文字。

对象是有用的抽象内存,用于存储有意义的数据位(当组合在一起时)表示某事的数据,无论是CarPerson还是{ {1}}。

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

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

答案 2 :(得分:2)

好问题。可以通过如何实现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