2013-10-20 21 views
4

以下代码段实施一个字符串。Java中的实习字符串

String str1="my"; 
String str2="string"; 
String concat1=str1+str2; 
concat1.intern(); 

System.out.println(concat1=="mystring"); 

表达concat1=="mystring"返回true因为concat1已经实习。


如果作为显示在下面的代码段中的给定的字符串mystring改变为string

String str11="str"; 
String str12="ing"; 
String concat11=str11+str12; 
concat11.intern(); 

System.out.println(concat11=="string"); 

比较表达concat11=="string"返回false。由concat11持有的字符串似乎没有被执行。我在这里忽略了什么?

我对Java 7的测试,更新11


编辑:

整个代码:

package test; 

public final class Test 
{ 
    public static void main(String... args) 
    { 
     String str11="my"; 
     String str12="string"; 
     String concat11=str11+str12; 
     concat11.intern(); 
     System.out.println(concat11=="mystring"); 

     String str1="str"; 
     String str2="ing"; 
     String concat1=str1+str2; 
     concat1.intern(); 
     System.out.println(concat1=="string"); 
    } 
} 
+0

注意上面做实习生的字符串,但你折腾掉实习版本。如果您打算立即使用它,则必须保存实习生函数调用的结果。 –

+1

'String.intern()'*返回*实参版本。它永远不会改变原始字符串(即'concat1'),因为字符串在Java中是不可变的。无论哪种方式,使用'equals'作为字符串比较(除非你有非常有说服力的理由来使用'intern')。 –

+1

您能否澄清一下,当您看到'concat11'返回false时,您正在运行一个包含这两个片段的程序? –

回答

3

当您使用intern()的字符串是不是在字符串池前面这个字符串将被放置在那里,每一个文字将使​​用引用。

但是,如果字符串池中已经有一些字面值,并且您将尝试在新创建的具有相同字符的字符串对象上调用intern(),它将不会放入池中,而只会返回对池中字符串的引用。此外,它不会更改对调用intern的原始字符串的引用。

由于Java在执行main方法之前加载并执行一些代码,因此在执行main代码之前,有可能会将一些文字放在字符串池中。
例如,字符串池将包含文字,例如"UTF-8","charset","charsetName",它们可能来自java.lang.Stringjava.nio.charset.Charset类。看起来"string"文字就是其中之一(我不确定它在哪里添加到字符串池)。

所以,当你调用

String str11="str"; 
String str12="ing"; 
String concat11=str11+str12; 
concat11.intern(); 

intern不会把"string"concat11在串池,因为那里是一个已经在那里等"string"文字(这样的你在=="string"部分使用)将使用一个来自字符串池,而不是从concat11

让我们验证这一理论:

String s = "ABCdef";// this string will be placed in 
        // string pool before rest of code 

String str1 = "ABC"; 
String str2 = "def"; 
String concat1 = str1 + str2; 
concat1.intern();//this will only return reference to literal from pool 

System.out.println(concat1 == "ABCdef");//false 


// here we don't have any "ABcd" literal in pool yet 
String strA = "AB"; 
String strB = "cd"; 
String concatAB = strA + strB; 
concatAB.intern();//so this will put String object from concatAB to pool 
System.out.println(concatAB == "ABcd");//and "ABcd" literal will use same object 

输出

false 
true 
+0

“*字符串池将包含诸如'UTF-8','charset','charsetName'等文字,它可能来自'java.lang.String'或'java.nio.charset.Charset'类。 '字符串'就是其中之一*“。如果真的如此,那么这就是答案。谢谢。 – Tiny

+0

@Tiny其实这样的文字可以出现在许多标准类中,所以我不确定它们是否来自这些文字。但是由于我们并不真正知道Java是如何为String字符串创建String对象,比如它使用哪个构造函数以及接下来调用哪些方法,我假设这些文字可能来自'String'类中的代码。 – Pshemo

6

如果你在同一个运行这两个代码段程序,然后concat1.intern()concat1添加到interned字符串池。但concat11.intern()不会向池中添加任何内容,因为"string"已经在池中(来自str2)。因此,您最后的比较是将concat11str2进行比较 - 并且这些不是同一个对象。

从Javadoc中在http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/String.html

当调用实习生方法中,如果池已经包含一个字符串等于由equals确定此字符串对象(Object)方法,然后是从池串返回。否则,将此String对象添加到池中,并返回对此String对象的引用。

+0

我已经在一段代码中注释掉了代码,但是它总是返回'false',以防采取的字符串是'string'和'true',否则(如果字符串不是'string')。对不起,我不明白。 – Tiny

+1

一个问题。让我们只运行第一个例子中的代码。如果我们移除'concat1.intern();'结果将是'false',但如果我们让它保持结果将是'true'。但在其他代码示例中,串联将返回''string''commenting'concat11.intern();'无关紧要,结果将始终为'false'。为什么? – Pshemo

+0

'concat11.intern()'不会更改池,因为'“string”'已经存在。所以评论它没有改变。 –