英文:
How does Java's intern() method behave on such Strings that are created during run time
问题
class Demo
{
public static void main(String[] args)
{
String s1 = new String("ABC");
String s2 = s1.concat("ABC");
String s3 = s2.intern();
System.out.println(s2 == s3); //true
String s4 = "ABCABC";
System.out.println(s3 == s4); //true
}
}
String s2 = s1.concat("ABC"); 会在堆区域创建一个新的字符串对象 "ABCABC"。
String s3 = s2.intern(); 应该会在字符串常量池中创建一个新的字符串对象。
因为这两个对象是不同的,它们的引用不应该相等。但似乎我漏掉了与 intern() 相关的一些重要内容。
英文:
class Demo
{
public static void main(String[] args)
{
String s1 = new String("ABC");
String s2 = s1.concat("ABC");
String s3 = s2.intern();
System.out.println(s2 == s3); //true
String s4 = "ABCABC";
System.out.println(s3 == s4); //true
}
}
String s2 = s1.concat("ABC"); would create a new String object "ABCABC" on the heap area.
String s3 = s2.intern(); should create a new String object onto the String constant pool.
Since these are two different objects, their references shouldn't be equal. But seems that i'm missing out on something important related to intern().
答案1
得分: 3
来自intern
的文档:
> 当调用intern
方法时,如果池中已经包含一个与该String对象相等的字符串,如通过equals(Object)
方法确定,则会返回池中的字符串。否则,该String对象将被添加到池中,并返回对该String对象的引用。
在调用intern
之前,字符串ABCABC
实际上已经存在于字符串池中!根据上述内容,如果字符串已经在池中,intern
只会返回池中的字符串,而不会在池中创建重复的字符串。这与您代码中的文字字面量创建的字符串实例相同。
“为什么字符串已经在池中呢?”我听到你在问。这是因为当字符串首次出现在源代码中时,它们不会被添加到字符串池中。编译器会收集源代码中的所有字符串字面量,并将它们放入类文件中。在程序开始运行时,类文件中的所有字符串都会被放入字符串池中。
要真正看到您期望的行为,您不能使用字符串字面量"ABCABC"
。例如,您可以将其替换为"ABC".concat("ABC")
:
String s4 = "ABC".concat("ABC"); // 这将创建一个新的字符串
英文:
From the docs of intern
:
> When the intern
method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object)
method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
Before intern
is called, the string ABCABC
is actually already in the string pool! And according to the above, if the string is already in the pool, intern
just returns the string from the pool, rather creating a duplicated string in the pool. This is the same instance as the string created from a literal in your code.
"Why is the string already in the pool?" I hear you ask. This is because strings are not added to the string pool when they first appear in the source code. The compiler collects all the string literals in the source code, and puts them in the class file. All the strings in the class file are put into the string pool when your program begins running.
To actually see the behaviour that you expect, you must not use the string literal "ABCABC"
. For example, you can replace it with "ABC".concat("ABC")
:
String s4 = "ABC".concat("ABC"); // this creates a new string
答案2
得分: 0
从 javadoc:
> 返回字符串对象的规范表示。
类 String 私下维护了一个最初为空的字符串池。
> 当调用 intern 方法时,如果池中已经包含一个与该 String 对象相等的字符串,如通过 equals(Object) 方法确定,则返回池中的字符串。否则,将此 String 对象添加到池中并返回对此 String 对象的引用。
> 由此可知,对于任何两个字符串 s 和 t,只有当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。
> 所有文字字符串和字符串值常量表达式都会被池化。字符串文字的定义在 Java™ 语言规范的第 3.10.5 节中。
因此,对于您的代码,内部字符串池的演变如下:
public static void main(String[] args)
{
String s1 = new String("ABC");
// "ABC" 生成一个新字符串并将其添加到池中。
// new String("ABC") 使用已经存在的 ABC 字符串生成一个不在池中的新副本。
// s1 指向不在内部池中的该字符串。
String s2 = s1.concat("ABC");
// "ABC" 已经存在。s1.concat("ABC") 创建一个新的字符串 ABCABC,添加到内部池中。s2 指向该字符串。
String s3 = s2.intern();
// s2.intern() 返回指向已经存在于内部池中的 ABCABC 的指针。s3 指向该字符串。
System.out.println(s2 == s3);
// 输出 true,因为内部池中存在的 ABCABC 被 s2 和 s3 共同指向。
String s4 = "ABCABC";
// ABCABC 已经存在于内部池中。s4 指向该字符串。
System.out.println(s3 == s4);
// 输出 true,因为 s2、s3、s4 都指向内部池中的同一个实例 ABCABC。
}
英文:
From javadoc:
> Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
> When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
> It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
> All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.
So the internal string pool for your code evolve as follow:
public static void main(String[] args)
{
String s1 = new String("ABC");
// "ABC" generate a new string and add it to intern pool.
// new String("ABC") uses the already present ABC string to generate a new copy that is not present in the pool.
// s1 points to that string that is not present in the internal pool
String s2 = s1.concat("ABC");
// "ABC" is already present. s1.concat("ABC") creates a new string ABCABC that is added to the internal pool. s2 point to that string
String s3 = s2.intern();
// s2.intern() returns a pointer to ABCABC that is already present in the internal pool. s3 points to that string
System.out.println(s2 == s3);
// Prints true because ABCABC present in the internal pool is pointed by both s2 and s3.
String s4 = "ABCABC";
// ABCABC is already present in the internal pool. s4 points to that string
System.out.println(s3 == s4);
// Prints true because all s2, s3, s4 points to the same instance ABCABC present in the internal pool.
}
答案3
得分: -1
依我看,intern
方法会在字符串常量池中添加字符串(如果该字符串不存在于常量池中),然后返回字符串引用。
因此,s4="ABCABC"
已经存在于字符串池中。
英文:
In my opinion,The intern method add the string into String constant pool if there is not the string,and then return the String reference.
so, s4="ABCABC" aready has existed the String pool
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论