天天看點

字元串比較: equals() 與 ==

最近作東西時字元串比較上出了點小問題,總結一下.

字元串為對象:

1."=="

所有"對象變量"用==作比較時比的是兩個對象在堆中的引用.

2."equals()"

所有對象的equals方法繼承自Object類的方法,而String重寫了equals方法的比較算法,它比較的是字元串的内容,即在堆中的了符序列

3.特點

字元串是一種比較特殊的對象,這裡的特殊指的是在運作期間,它的指派直接改變引用(當然,任何對象的指派都是直接改變的引用,隻不過字元串這種東西往往讓人容易了解為它是在原來的基礎上操作的,尤其是+=這類操作),而不是在原來所引用的記憶體塊中做修改.(是以有了StringBuffer類的出現)

結論:

1.

String s1 = "hello";

String s2 = "hello";

System.out.println(s1.equals(s2));  //true

System.out.println(s1 == s2);       //true

按照上面的說法,第一個true不難了解.

而第2個之是以也為true是因為,java編譯器用的類似于C語言中的"文字池機制",即在源代碼中所有的字元串常量聲明全部放在一塊記憶體區域,是以當一個字元串聲明時指派的是一個字元串常量,那麼如果"文字池"中有這個字元串常量,編譯器将直接把它的引用指派給這個變量.

是以在用==來比較s1和s2時,将會得到true.

2.

String s1 = "hello";

String s2 = "hello";

s1 = s1 + "a";

s2 = s2 + "a";

System.out.println(s1.equals(s2));  //true

System.out.println(s1 == s2);       //false

第3,4行的指派操作在運作期間執行,根據上面的知識點3:兩個變量的引用将會發生改變.是以這時用==相比時将會得到false;

(在運作期間所得到的字元串内容,将不會放到所謂的"文字池"之中,然後如果有相同内容的變量引用相同内容,這樣作的話需要每次字元串改變時需要檢查它的内容,并再在文字池中查找看是否有相同内容的常量,太過浪費效率.)

("文字池機制"也許也是為什麼字元串對象在作更改時,直接改變引用的一個原因,因為如果直接對引用的記憶體塊作操作的話,另一個指向相同引用的字元串變量将也會發什麼改變,發生邏輯混淆)

3.

代碼略.

當字元串對象從不同地方(字元串常量;本地資源檔案讀取;網絡傳輸:如表單送出;等等)獲得時:除了是編譯期間用相同常量指派的字元串變量的引用相同外,其它的全部是新的引用.是以,與這種變量直接用==相比時将得到false,即使内容相同

應用結論:

1.如果是單純的比較字元串内容的話:用equals()

2.如果确實是要比較兩個變量的引用的話:用==