1

Stackoverflow充满了与不同类型的 String 初始化相关的问题。我明白String s = "word"String s = new String("word"). 所以没有必要“触及”那个话题。

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

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

但我不明白SCP是否存储对象文字。它们是完全不同的概念。对象一个实体,而文字只是一个值。那么这个问题的正确答案是什么。SCP是否存储对象文字?我知道它不能两者兼而有之:)

4

3 回答 3

3

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

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

我知道不可能两者兼有

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

于 2020-10-06T04:37:06.293 回答
3

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

String s = "Hello World";

"Hello World"是一个字符串文字。

对象是有意义的内存位的有用抽象,其中的数据(当组合在一起时)代表某物,无论是 a CarPerson还是String

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

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

于 2020-10-06T04:44:48.387 回答
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

于 2020-10-06T04:52:44.740 回答