1.String
String:字符串常量,字符串長度不可變滋恬。Java中String是immutable(不可變)的聊训。
用于存放字符的數(shù)組被聲明為final的,因此只能賦值一次恢氯,不可再更改带斑。
2.StringBuffer(JDK1.0)
StringBuffer:字符串變量(Synchronized,即線程安全)勋拟。如果要頻繁對字符串內(nèi)容進(jìn)行修改勋磕,出于效率考慮最好使用StringBuffer,如果想轉(zhuǎn)成String類型指黎,可以調(diào)用StringBuffer的toString()方法朋凉。
Java.lang.StringBuffer線程安全的可變字符序列。在任意時間點上它都包含某種特定的字符序列醋安,但通過某些方法調(diào)用可以改變該序列的長度和內(nèi)容杂彭。可將字符串緩沖區(qū)安全地用于多個線程吓揪。
StringBuffer 上的主要操作是 append 和 insert 方法亲怠,可重載這些方法,以接受任意類型的數(shù)據(jù)柠辞。每個方法都能有效地將給定的數(shù)據(jù)轉(zhuǎn)換成字符串团秽,然后將該字符串的字符追加或插入到字符串緩沖區(qū)中。append 方法始終將這些字符添加到緩沖區(qū)的末端叭首;而 insert 方法則在指定的點添加字符习勤。例如,如果 z 引用一個當(dāng)前內(nèi)容是“start”的字符串緩沖區(qū)對象焙格,則此方法調(diào)用 z.append("le") 會使字符串緩沖區(qū)包含“startle”图毕,而 z.insert(4, "le") 將更改字符串緩沖區(qū),使之包含“starlet”眷唉。
3.StringBuilder(JDK5.0)
StringBuilder:字符串變量(非線程安全)予颤。在內(nèi)部,StringBuilder對象被當(dāng)作是一個包含字符序列的變長數(shù)組冬阳。
java.lang.StringBuilder是一個可變的字符序列蛤虐,是JDK5.0新增的。此類提供一個與 StringBuffer 兼容的 API肝陪,但不保證同步驳庭。該類被設(shè)計用作 StringBuffer 的一個簡易替換,用在字符串緩沖區(qū)被單個線程使用的時候(這種情況很普遍)氯窍。
其構(gòu)造方法如下:
構(gòu)造方法 描述
StringBuilder() 創(chuàng)建一個容量為16的StringBuilder對象(16個空元素)
StringBuilder(CharSequence cs) 創(chuàng)建一個包含cs的StringBuilder對象嚷掠,末尾附加16個空元素
StringBuilder(int initCapacity) 創(chuàng)建一個容量為initCapacity的StringBuilder對象
StringBuilder(String s) 創(chuàng)建一個包含s的StringBuilder對象捏检,末尾附加16個空元素
在大部分情況下荞驴,StringBuilder > StringBuffer不皆。這主要是由于前者不需要考慮線程安全。
4.三者區(qū)別
String 類型和StringBuffer的主要性能區(qū)別:String是不可變的對象, 因此在每次對String 類型進(jìn)行改變的時候熊楼,都會生成一個新的 String 對象霹娄,然后將指針指向新的 String 對象,所以經(jīng)常改變內(nèi)容的字符串最好不要用 String 鲫骗,因為每次生成對象都會對系統(tǒng)性能產(chǎn)生影響策治,特別當(dāng)內(nèi)存中無引用對象多了以后搁廓, JVM 的 GC 就會開始工作,性能就會降低。
使用 StringBuffer 類時沥邻,每次都會對 StringBuffer 對象本身進(jìn)行操作,而不是生成新的對象并改變對象引用弄痹。所以多數(shù)情況下推薦使用 StringBuffer 罩引,特別是字符串對象經(jīng)常改變的情況下。
在某些特別情況下排苍, String 對象的字符串拼接其實是被 Java Compiler 編譯成了 StringBuffer 對象的拼接沦寂,所以這些時候 String 對象的速度并不會比 StringBuffer 對象慢,例如:
String s1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
生成 String s1對象的速度并不比 StringBuffer慢淘衙。其實在Java Compiler里传藏,自動做了如下轉(zhuǎn)換:
Java Compiler直接把上述第一條語句編譯為:
String s1 = “This is only a simple test”;
所以速度很快。但要注意的是彤守,如果拼接的字符串來自另外的String對象的話毯侦,Java Compiler就不會自動轉(zhuǎn)換了,速度也就沒那么快了具垫,例如:
String s2 = “This is only a”;
String s3 = “ simple”;
String s4 = “ test”;
String s1 = s2 + s3 + s4;
這時候侈离,Java Compiler會規(guī)規(guī)矩矩的按照原來的方式去做,String的concatenation(即+)操作利用了StringBuilder(或StringBuffer)的append方法實現(xiàn)做修,此時霍狰,對于上述情況,若s2饰及,s3蔗坯,s4采用String定義,拼接時需要額外創(chuàng)建一個StringBuffer(或StringBuilder)燎含,之后將StringBuffer轉(zhuǎn)換為String宾濒;若采用StringBuffer(或StringBuilder),則不需額外創(chuàng)建StringBuffer屏箍。
5.使用策略
1)基本原則:如果要操作少量的數(shù)據(jù)绘梦,用String 橘忱;單線程操作大量數(shù)據(jù),用StringBuilder 卸奉;多線程操作大量數(shù)據(jù)钝诚,用StringBuffer。
(2)不要使用String類的"+"來進(jìn)行頻繁的拼接榄棵,因為那樣的性能極差的凝颇,應(yīng)該使用StringBuffer或StringBuilder類,這在Java的優(yōu)化上是一條比較重要的原則疹鳄。例如:
String result = "";
for (String s : hugeArray) {
result = result + s;
}
// 使用StringBuilder
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
sb.append(s);
}
String result = sb.toString();
當(dāng)出現(xiàn)上面的情況時拧略,顯然我們要采用第二種方法,因為第一種方法瘪弓,每次循環(huán)都會創(chuàng)建一個String result用于保存結(jié)果垫蛆,除此之外二者基本相同(對于jdk1.5及之后版本)。
(3)為了獲得更好的性能腺怯,在構(gòu)造 StringBuffer 或 StringBuilder 時應(yīng)盡可能指定它們的容量袱饭。當(dāng)然,如果你操作的字符串長度(length)不超過 16 個字符就不用了瓢喉,當(dāng)不指定容量(capacity)時默認(rèn)構(gòu)造一個容量為16的對象宁赤。不指定容量會顯著降低性能。
(4)StringBuilder一般使用在方法內(nèi)部來完成類似"+"功能栓票,因為是線程不安全的决左,所以用完以后可以丟棄。StringBuffer主要用在全局變量中走贪。
(5)相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升佛猛,但卻要冒多線程不安全的風(fēng)險。而在現(xiàn)實的模塊化編程中坠狡,負(fù)責(zé)某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環(huán)境中運行继找,因此:除非確定系統(tǒng)的瓶頸是在 StringBuffer 上,并且確定你的模塊不會運行在多線程模式下逃沿,才可以采用StringBuilder婴渡;否則還是用StringBuffer。