之前關於String的理解僅限於三點:
一、String 是final類,不可繼承
二、String 類比較字符串相等時時不能用「 == 」,只能用 "equals"
三、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"字符串做爲String對象存儲在內存中的一個獨立位置。
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"。