调用intern()时字符串常量池返回哪个String对象?规则解析
Great question! Let's break this down step by step, starting with clearing up a common misunderstanding about the string pool (officially called the StringTable in the JVM).
Correcting a Key Misconception
You mentioned "此时常量池中存在两个字符序列相同的String对象" — this is incorrect. When you execute new String("string"):
- First, the JVM checks the StringTable for a string with the character sequence "string". Since you already created
firstusing the literal"string", this entry already exists in the StringTable. - The
new String()call then creates a brand-new String object in the heap. This heap object reuses the character array from the StringTable entry (in JDK 7+), but it is not stored in the StringTable itself.
So at this point, the StringTable only contains one "string" object (the one first points to), while second is an independent object in the heap.
Why intern() Returns the Literal's Reference
The Java Language Specification (JLS) states that when calling intern():
如果常量池中已存在一个与该String对象equals(java.lang.Object)方法判定相等的字符串,则返回常量池中的字符串。
In practice, the JVM's StringTable is designed to store exactly one reference per unique character sequence. Here's what happens with your code:
- The
"string"literal inString third = "string".intern();is already a reference to the object in the StringTable (the same onefirstpoints to). - Calling
intern()on a String that's already present in the StringTable simply returns itself, because the JLS check finds an equal string (itself) already exists.
This is why System.identityHashCode(first) and System.identityHashCode(third) match — they reference the exact same object in the StringTable.
What If We Called intern() on second?
To further clarify, if you modified your code to call second.intern():
- The JVM checks the StringTable for a string equal to
second(which is "string"). It finds the existing entry from the literal, sosecond.intern()would return the same reference asfirstandthird. - The
secondobject would still remain in the heap, but it wouldn't be added to the StringTable since an equal entry already exists.
Key Rules for intern() Return Values
To wrap up, here are the core rules that determine what intern() returns:
- If the StringTable already contains a string equal to the calling String (via
equals()), return the reference to that StringTable entry. - If the StringTable does not contain such a string, add the calling String's reference to the StringTable and return that reference (this applies to heap-created Strings that haven't been interned yet).
- Most importantly: The StringTable will never hold two different references to strings that are equal (per
equals()) — it's a deduplicated collection by design.
内容的提问来源于stack exchange,提问作者0lt

