Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java';s intern()方法在运行时创建的字符串上运行_Java_String_Constants_Pool - Fatal编程技术网

Java';s intern()方法在运行时创建的字符串上运行

Java';s intern()方法在运行时创建的字符串上运行,java,string,constants,pool,Java,String,Constants,Pool,字符串s2=s1.concat(“ABC”);将在堆区域上创建一个新的字符串对象“ABCABC”。 字符串s3=s2.intern();应在字符串常量池中创建新的字符串对象 因为这是两个不同的对象,所以它们的引用不应该相等。但是似乎我错过了一些与intern()相关的重要内容。来自intern: 调用intern方法时,如果池中已包含一个字符串,该字符串等于equals(object)方法确定的该字符串对象,则返回池中的字符串。否则,此字符串对象将添加到池中,并返回对此字符串对象的引用 在调用i

字符串s2=s1.concat(“ABC”);将在堆区域上创建一个新的字符串对象“ABCABC”。 字符串s3=s2.intern();应在字符串常量池中创建新的字符串对象

因为这是两个不同的对象,所以它们的引用不应该相等。但是似乎我错过了一些与intern()相关的重要内容。

来自
intern

调用
intern
方法时,如果池中已包含一个字符串,该字符串等于
equals(object)
方法确定的该字符串对象,则返回池中的字符串。否则,此字符串对象将添加到池中,并返回对此字符串对象的引用

在调用
intern
之前,字符串
ABCABC
实际上已经在字符串池中了!根据上面的说明,如果字符串已经在池中,
intern
只是从池中返回字符串,而不是在池中创建重复的字符串。这与从代码中的文本创建的字符串是同一个实例

“为什么绳子已经在游泳池里了?”我听到你问。这是因为字符串第一次出现在源代码中时没有添加到字符串池中。编译器收集源代码中的所有字符串文本,并将它们放入类文件中。当程序开始运行时,类文件中的所有字符串都会放入字符串池

要实际查看您期望的行为,您不能使用字符串literal
“ABCABC”
。例如,您可以将其替换为
“ABC”。concat(“ABC”)


在我看来,intern方法将字符串添加到字符串常量池中(如果没有字符串),然后返回字符串引用

因此,s4=“ABCABC”aready已存在字符串池

来自:

返回字符串对象的规范表示形式。 最初为空的字符串池由类字符串私下维护。 调用intern方法时,如果池中已经包含一个等于equals(object)方法确定的该字符串对象的字符串,则返回池中的字符串否则,此字符串对象将添加到池中,并返回对此字符串对象的引用。 因此,对于任意两个字符串s和t,s.intern()==t.intern()为真当且仅当s.equals(t)为真时。 所有文字字符串和字符串值常量表达式都被插入。字符串文本在Java的第3.10.5节中定义™ 语言规范

因此,代码的内部字符串池的演变如下:

String s4 = "ABC".concat("ABC"); // this creates a new string

concat()在执行之前无法确定最终字符串的外观。字符串s2实际上会在堆区域中分配。考虑这个例子,类main {public static Valm main(String []ARGS){String S1=新字符串(“abc”);字符串S2= S1.CONTAT(“ABC”);字符串S3=“ABCABC”;Soal.Out.PrtLn(S2= S3);}如果s2已经在池中,那么为什么s2==s3会导致false。@ZabiKhan在答案发布后请不要更改您的问题,因为这会使答案无效。我已经回滚了您的编辑。@ZabiKhan,那么您是在问为什么
s2==s3
是真的?那么你的问题就如我所说的那样以重复的形式结束了。更正:编译时常量添加到池中的时间取决于实现。在此特定示例中,当
s2==s3
true
时,证明
“ABCABC”
不在池中。否则,
s1.concat(“ABC”)
的结果无法成为池成员。然后,当
字符串s4=“ABCABC”时,常量被解析为添加了
字符串s3=s2.intern()的同一个对象。因此,
s3==s4
保证为
true
,但在具有急切常量解析的环境中,
s2==s3
将为
false
。通常,“移动到常量池”和“留在堆中”是不合适的短语。所有对象都存储在堆中。运行时字符串池只是一些字符串的引用表。向池中添加字符串意味着添加引用。字符串对象本身保持不变。请重新访问问题。
String s4 = "ABC".concat("ABC"); // this creates a new string
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.
}