String,Stringbuffer,Stringbuilder

  • String

定義:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {

可以看出 String 是 final 類型的流酬,表示該類不能被其他類繼承,同時該類實現(xiàn)了三個接口:java.io.Serializable Comparable<String> CharSequence

屬性:

private final char value[];

這是一個字符數(shù)組物延,并且是 final 類型捐友,用于存儲字符串內(nèi)容。從 final 關鍵字可以看出逆济,String 的內(nèi)容一旦被初始化后蜀肘,其不能被修改的绊汹。
所以對String的修改都是將引用指向了新的字符串。

構造方法:

String可以用byte[]扮宠,String西乖,StringBuffer,StringBuilder涵卵,char[]構造
其中用byte[]構造的時候浴栽,涉及到編碼問題,編碼用Charset指定轿偎。
其中還有一個構造方法要注意:

String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
    }

這個構造方法是把char[]的引用直接給String內(nèi)部的char[],而其他構造方法則是new一個char[],值復制典鸡。這個是一個protected方法,所以不用擔心安全問題坏晦。

其他方法:

String的其他方法在api文檔直接查就可以了萝玷,這里我就不列舉了。
由于String的特性昆婿,對String有修改的方法都是返回一個新的String對象球碉。

編碼問題

之前提到的String內(nèi)部是用一個char[]來存儲的。而char是unicode編碼仓蛆,是兩個字節(jié)存一個字符睁冬。
但是用getbytes()方法獲得的byte[]的長度并不是char[]長度*2。原因是getbytes()方法獲得的byte[]并不是unicode編碼看疙。String類型的默認編碼方式是和本地編碼方式相關豆拨。編碼方式也可以指定。

之所以提這個是因為我之前寫的代碼需要把固定長度的String轉(zhuǎn)換為固定長度的byte[]能庆,但是GBK,UTF-8,UTF-16編碼都是不等長編碼施禾,而iso8859-1編碼不支持中文。而在charest的編碼集里沒有找到等長編碼的unicode編碼搁胆。
最后我用toCharArray()獲得String內(nèi)部的char[]的副本弥搞,因為char是unicode編碼邮绿,所以我把char[]轉(zhuǎn)換成了char[]長度*2的byte[]數(shù)組。

String常量池與字符串拼接性能優(yōu)化

String常量池

String常量池是一個初始為空的字符串池攀例,它由類 String 私有地維護船逮。

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

當我們創(chuàng)建String對象采用字面量形式時,JVM首先會對這個字面量進行檢查粤铭,如果常量池中存放有該字面量傻唾,則直接使用,否則創(chuàng)建新的對象并將其引用放入常量池中承耿。

String s1="gh";
String s2=new String("gh");
s2.intern();
System.out.println(s1==s2);//false;
s2=s2.intern();
System.out.println(s1==s2);//true;

當調(diào)用 intern 方法時,如果池已經(jīng)包含一個等于此 String 對象的字符串(equals(Object)方法確定)伪煤,則返回池中的字符串加袋。否則,將此 String 對象添加到池中抱既,并返回此 String 對象的引用职烧。

常量池中存的是對對象的引用,存儲于JVM的方法區(qū)中防泵,而且引用的對象存儲于堆中蚀之。

當常量池中的引用沒有被任何變量引用時,就會被GC回收捷泞!

String常量池
String s1="a"+"b"+"c";

正常情況下足删,執(zhí)行聲明s1,代碼會生成3個對象锁右,即對象a失受、對象ab、對象abc咏瑟,其中對象a和對象ab都是中間的臨時變量拂到,最后的對象abc才賦值給了s1。因此在使用字符串拼接的時候码泞,拼接的數(shù)量越多兄旬,性能越低!
但是java編譯器在編譯的時候做了優(yōu)化余寥,在編譯時新建一個對象StringBuilder來拼接领铐,這樣就避免了產(chǎn)生很多臨時對象,從而提升了性能劈狐!

String s="";
for(int i=0;i<length;i++){
   s+=i;
}

但是這個做法效率會很低罐孝。因為循環(huán)內(nèi),每次都在做字符串拼接肥缔,每次都在產(chǎn)生一個StringBuilder對象莲兢,造成內(nèi)存的浪費!因此這種錯誤要盡量避免,稍做以下優(yōu)化即可完美改造:

String s="";
StringBuilder sb=new StringBuilder();
for(int i=0;i<length;i++){
    sb.append(i);
}
  • Stringbuffer與Stringbuilder

在線程安全上改艇,StringBuilder是線程不安全的收班,而StringBuffer是線程安全的。因為StringBuffer的大部分方法帶有synchronized修飾符谒兄,而StringBuilder沒有摔桦。

StringBuilder:適用于單線程下在字符緩沖區(qū)進行大量操作的情況
StringBuffer:適用多線程下在字符緩沖區(qū)進行大量操作的情況

這兩個類的大多數(shù)方法都是繼承自父類AbstractStringBuilder〕衅#或者做了少量的應用邻耕。所以要了解這兩個類,應該去了解父類AbstractStringBuilder燕鸽。

/**
     * 底層存儲的字符數(shù)組
     */
    char[] value;

    /**
     * 用于記錄存的字符的數(shù)目
     */
    int count;

從它的成員變量我們可以發(fā)現(xiàn)和ArrayList的有些類似兄世,事實上看過源碼之后你會發(fā)現(xiàn)他們的底層機制是很類似的。

我們主要研究append()方法啊研,以append(String str)為例

public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

其實就是把str的內(nèi)容復制添加到內(nèi)部的char數(shù)組value的末尾御滩。
關鍵是ensureCapacityInternal(count + len);這行代碼。它的作用是檢查value的容量夠不夠党远,不夠的話就擴充削解,這個和ArrayList的擴充機制基本一致,看過源碼后你會發(fā)現(xiàn)沟娱,連寫法都差不多氛驮。

int newCapacity = value.length * 2 + 2;

新的容量是舊容量的2倍+2,默認容量是16。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末济似,一起剝皮案震驚了整個濱河市柳爽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碱屁,老刑警劉巖磷脯,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異娩脾,居然都是意外死亡赵誓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門柿赊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俩功,“玉大人,你說我怎么就攤上這事碰声」铗眩” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵胰挑,是天一觀的道長蔓罚。 經(jīng)常有香客問我椿肩,道長,這世上最難降的妖魔是什么豺谈? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任郑象,我火速辦了婚禮,結果婚禮上茬末,老公的妹妹穿的比我還像新娘厂榛。我一直安慰自己,他們只是感情好丽惭,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布击奶。 她就那樣靜靜地躺著,像睡著了一般责掏。 火紅的嫁衣襯著肌膚如雪正歼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天拷橘,我揣著相機與錄音,去河邊找鬼喜爷。 笑死冗疮,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的檩帐。 我是一名探鬼主播术幔,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼湃密!你這毒婦竟也來了诅挑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤泛源,失蹤者是張志新(化名)和其女友劉穎拔妥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體达箍,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡没龙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缎玫。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硬纤。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赃磨,靈堂內(nèi)的尸體忽然破棺而出筝家,到底是詐尸還是另有隱情,我是刑警寧澤邻辉,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布溪王,位于F島的核電站腮鞍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏在扰。R本人自食惡果不足惜缕减,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芒珠。 院中可真熱鬧桥狡,春花似錦、人聲如沸皱卓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娜汁。三九已至嫂易,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掐禁,已是汗流浹背怜械。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留傅事,地道東北人缕允。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓婆誓,卻偏偏與公主長得像囤官,于是被迫代替她去往敵國和親争涌。 傳聞我的和親對象是個殘疾皇子猎唁,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容