以前關於String的理解僅限於三點:
1、String 是final類,不可繼承
2、String 類比較字串相等時時不能用“ == ”,只能用 "equals"
3、String 類不可更改
String 使用非常方便,因此一般涉及字串時都用該類進行字串處理
至於String類的類在機制,則極少去探究。
直到讀到下面這個例子。
class X
{
public static String strX="hello";
}
class Y
{
public static String strY="hello";
}
class Z
{
public static String strZ="hell"+"o";
}
class Test
{
public static void main(String[] args)
{
System.out.println( X.strX==Y.strY);
System.out.println( X.strX==Z.strZ);
String s1="hel";
String s2="lo";
System.out.println( X.strX==(s1+s2));
System.out.println( X.strX==(s1+s2).intern());
}
}
按照我的理解,類X,類Y,類Z中的三個常量字串屬於不同的對象,用 == 操作符比較,那麼結果必然是 false,輸出應該為:
false
false
false
false
但實際上輸出確是:
true
true
false
true
使我大惑不解。並因此找了許多資料來看(尤其是C++和Java比較編程,裡面解釋比較詳細),終於逐漸明白了原因。
== 只有在兩個比較對象指向同一對象時,其值才為true。X.strX==Y.strY 與 X.strX==Z.strZ 測試結果都為true,說明這三個常量指向的都是同一個對象。
在JAVA中,String 是字串常量。由相同序列的字元組成的兩個字串屬於同一對象,位於記憶體中的同一個位置。每個字串常量只有一個 String 對象來表示。即使這個字串常量出現在一個程式的不同位置甚至一個程式的不同程式包中。也就是說,X.strX 與 Y.strY 由雩都是同一字元序列,因此 指向的肯定是同一對象。
Z.strZ 也是如此。"hell"+"o",兩個常量字串相加後,建立了一個新的字串常量(這個工作是編譯期間完成的),它與 X.strX ,Y.strY有相同的字元序列,因此指向同一對象 。
雖然一個常量運算式將兩個字串常量連結在一起的結果在編譯器已完成,但是
String s1="hel";
String s2="lo";
String s3=s1+s2;
這段代碼中,s3隻能在運行期間建立。這三條語句所建立的"hello"字串作為StringObject Storage Service在記憶體中的一個獨立位置。
Java提供一個機制,通過String類定義的intern()方法把一個運行時建立的字串加到字串常量池(如果它還沒有入池)。如果上面的三條代碼改為:
String s1="hel";
String s2="lo";
String s3=(s1+s2).intern();
java將把 s1+s2 所返回的字串對象中的字元序列與已經儲存在字串常量池中的字串進行比較。如果找到一個匹配,intern()就返回這個字串的引用。如果沒有找到匹配,s1+s2 所返回的字串將被加入到字串常量池中,並返回這個字串常量的引用。
這就解釋了為社麼X.strX==(s1+s2)返回false,而X.strX==(s1+s2).intern()返回true。(s1+s2).intern()指向strX,strY,StrX指向的字串常量"hello"。