2013-10-20 56 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」'已經存在。所以評論它沒有改變。 –