Java string類

轉載 http://sarin.iteye.com/blog/603684 這篇文章講的太好了!

先看一段代碼:

public class Test {  
    public static void main(String[] args){  
        String str = "abc";  
        String str1 = "abc";  
        String str2 = new String("abc");  
        System.out.println(str == str1);  
        System.out.println(str1 == "abc");  
        System.out.println(str2 == "abc");  
        System.out.println(str1 == str2);  
        System.out.println(str1.equals(str2));  
        System.out.println(str1 == str2.intern());  
        System.out.println(str2 == str2.intern());  
        System.out.println(str1.hashCode() == str2.hashCode());  
    }  
}

Java語言使用內存的時候,棧內存主要保存以下內容:基本數據類型和對象的引用,而堆內存存儲對象,棧內存的速度要快于堆內存。總結成一句話就是:引用在棧而對象在堆
Java中的比較有兩種,是==和equals()方法,equals()是Object類的方法,定義在Object類中的equals()方法是如下實現的:

public boolean equals(Object obj){  
        return (this==obj);  
}

String類重寫了equals()方法,改變了這些類型對象相等的原則,即判斷對象是否相等依據的原則為判斷二者的內容是否相等。

了解以上內容后我們來說說String,String類的本質是字符數組char[],其次String類是final的,是不可被繼承的,這點可能被大多數人忽略,再次String是特殊的封裝類型,使用String時可以直接賦值,也可以用new來創建對象,但是這二者的實現機制是不同的。還有一個String池的概念,Java運行時維護一個String池,池中的String對象不可重復,沒有創建,有則作罷。String池不屬于堆和棧,而是屬于常量池。
下面分析上方代碼的真正含義:

String str = "abc";  
String str1= "abc";

第一句的真正含義是在String池中創建一個對象”abc”,然后引用時str指向池中的對象”abc”。第二句執行時,因為”abc”已經存在于String池了,所以不再創建,則str==str1返回true就明白了。str1==”abc”肯定正確了,在String池中只有一個”abc”,而str和str1都指向池中的”abc”,就是這個道理。

String str2 = new String("abc");

單獨這句話創建了2個String對象,而基于上面兩句,只在棧內存創建str2引用,在堆內存上創建一個String對象,內容是”abc”,而str2指向堆內存對象的首地址。

下面就是str2==”abc”的問題了,顯然不對,”abc”是位于String池中的對象,而str2指向的是堆內存的String對象,==判斷的是地址,肯定不等了。

str1.equals(str2),這個是對的,前面說過,String類的equals重寫了Object類的equals()方法,實際就是判斷內容是否相同了。

下面說下intern()方法,在JavaDoc文檔中,這樣描述了intern()方法:返回字符串對象的規范化表示形式。怎么理解這句話?實際上過程是這樣進行的:該方法現在String池中查找是否存在一個對象,存在了就返回String池中對象的引用。

那么本例中String池存在”abc”,則調用intern()方法時返回的是池中”abc”對象引用,那么和str/str1都是等同的,和str2就不同了,因為str2指向的是堆內存。

hashCode()方法是返回字符串內容的哈希碼,既然內容相同,哈希碼必然相同,那他們就相等了,這個容易理解。

再看下面的例子:

public class Test {  
    private static String str = "abc";  
    public static void main(String[] args) {  
        String str1 = "a";  
        String str2 = "bc";  
         String combo = str1 + str2;  
        System.out.println(str == combo);  
        System.out.println(str == combo.intern());  
    }  
}

這個例子用來說明用+連接字符串時,實際上是在堆內容創建對象,那么combo指向的是堆內存存儲”abc”字符串的空間首地址,顯然str==combo是錯誤的,而str==combo.intern()是正確的,在String池中也存在”abc”,那就直接返回了,而str也是指向String池中的”abc”對象的。此例說明任何重新修改String都是重新分配內存空間,這就使得String對象之間互不干擾。也就是String中的內容一旦生成不可改變,直至生成新的對象。

同時問題也來了,使用+連接字符串每次都生成新的對象,而且是在堆內存上進行,而堆內存速度比較慢(相對而言),那么再大量連接字符串時直接+是不可取的,當然需要一種效率高的方法。Java提供的StringBuffer和StringBuilder就是解決這個問題的。區別是前者是線程安全的而后者是非線程安全的,StringBuilder在JDK1.5之后才有。不保證安全的StringBuilder有比StringBuffer更高的效率。

自JDK1.5之后,Java虛擬機執行字符串的+操作時,內部實現也是StringBuilder,之前采用StringBuffer實現。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容