Stackoverflow 充满了与不同类型的String初始化相关的问题。我了解String s = "word"
与String s = new String("word")
有何不同。因此,无需“触摸”该主题。
我注意到有不同的人提到String池存储常量/对象/文字。
常量是可以理解的,因为它们是最终的,因此它们总是“呆在”那里。是的,重复项也不会存储在 SCP 中。
但是我不知道 SCP 是否存储对象或文字。它们是完全不同的概念。 对象是实体,而文字是只是一个值。那么正确的答案是什么。 SCP 是否存储对象或文字?我知道不能同时都是:)
答案 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"
是字符串文字。
对象是有用的抽象内存,用于存储有意义的数据位(当组合在一起时)表示某事的数据,无论是Car
,Person
还是{ {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;
}