分享知識-快樂自己:Java 中 的String,StringBuilder,StringBuffer三者的區別
這三個類之間的區別主要是在兩個方面,即執行速度和執行緒安全這兩方面。
1):首先說執行速度,或者說是執行速度,在這方面執行速度快慢為:StringBuilder > StringBuffer > String
String:最慢的原因:
String:為字串常量,而StringBuilder和StringBuffer均為字串變數,即String物件一旦建立之後該物件是不可更改的,但後兩者的物件是變數,是可以更改的。
以下面一段程式碼為例:
String str="abc";
System.out.println(str);
str=str+"de";
System.out.println(str);
如果執行這段程式碼會發現先輸出“abc”,然後又輸出“abcde”,好像是str這個物件被更改了,其實,這只是一種假象罷了,
JVM對於這幾行程式碼是這樣處理的,首先建立一個String物件str,並把“abc”賦值給str,然後在第三行中,其實JVM又建立了一個新的物件也名為str,
然後再把原來的str的值和“de”加起來再賦值給新的str;
而原來的str就會被JVM的垃圾回收機制(GC)給回收掉了,所以,str實際上並沒有被更改,也就是前面說的String物件一旦建立之後就不可更改了。
所以,Java中對String物件進行的操作實際上是一個不斷建立新的物件並且將舊的物件回收的一個過程,所以執行速度很慢。
而 StringBuilder 和 StringBuffe r的物件是變數,對變數進行操作就是直接對該物件進行更改,而不進行建立和回收的操作,所以速度要比String快很多。
另外,有時候我們會這樣對字串進行賦值
String str="abc"+"de";
StringBuilder stringBuilder=new StringBuilder().append("abc").append("de");
System.out.println(str);
System.out.println(stringBuilder.toString());
這樣輸出結果也是“abcde”和“abcde”,但是String的速度卻比StringBuilder的反應速度要快很多,這是因為第1行中的操作和
String str="abcde";
是完全一樣的,所以會很快,而如果寫成下面這種形式
String str1="abc";
String str2="de";
String str=str1+str2;
那麼JVM就會像上面說的那樣,不斷的建立、回收物件來進行這個操作了。速度就會很慢。
再來說執行緒安全:
線上程安全上,StringBuilder是執行緒不安全的,而StringBuffer是執行緒安全的
如果一個 StringBuffer 物件在字串緩衝區被多個執行緒使用時,StringBuffer 中很多方法可以帶有synchronized關鍵字,所以可以保證執行緒是安全的,
但StringBuilder的方法則沒有該關鍵字,所以不能保證執行緒安全,有可能會出現一些錯誤的操作。
所以如果要進行的操作是多執行緒的,那麼就要使用StringBuffer,但是在單執行緒的情況下,還是建議使用速度比較快的StringBuilder。
總結一下:
String:適用於少量的字串操作的情況
StringBuilder:適用於單執行緒下在字元緩衝區進行大量操作的情況
StringBuffer:適用多執行緒下在字元緩衝區進行大量操作的情況
測試執行緒安全測試Demo:
(使用多執行緒進行測試)
/***
* 從執行緒角度:
* StringBuffer執行緒安全 StringBuilder不安全
*/
@Test
public void testStringBuilderAndStringBuffer() {
final MyString sb = new MyString();
final StringBuilder sbBuilder = new StringBuilder();
final StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) {
sb.append(1);
sbBuilder.append("1");
stringBuffer.append("1");
System.out.println(sb.getNum() + "-" + sbBuilder.length() + "-" + stringBuffer.length());
}
}
}).start();
}
}
/***
* 內部類
*/
class MyString {
private Integer num = 0;
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public synchronized void append(Integer num) {
this.num = this.num + num;
}
}
最終結果:很明顯 StringBuilder 是不安全的有些執行緒被其他的搶佔了