Java的intern()方法如何对在运行时创建的此类字符串进行操作

huangapple go评论80阅读模式
英文:

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

huangapple
  • 本文由 发表于 2020年9月2日 17:17:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63702466.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定