咱們先對比下String, StringBuffer, StringBuilder這三個類。他們的主要區別通常體如今線程安全和執行效率上。java
類名 | String | StringBuffer | StringBuilder |
---|---|---|---|
線程安全 | 安全(final修飾) | 安全 | 不安全 |
字符串類型 | 常量 | 變量 | 變量 |
執行效率 | 最慢 | 介於兩者之間 | 最快 |
String類是用final修飾符修飾的,它的值是不可修改的,所以是線程安全的。 若是一個StringBuffer對象在緩衝區被多個線程使用時,由於StringBuffer的方法都是帶有synchronized關鍵字的,因此能夠保證線程安全,而StringBuilder的方法沒有該關鍵字,不能保證線程安全,所以可能會出現一些操做錯誤。多線程狀況下建議使用StringBuffer,單線程建議使用速度較快的StringBuilder。安全
先看一段代碼:多線程
String str = "abcdef"; str = str + "123456"; System.out.println(str);
這段代碼輸出的結果是: 「abcdef123456」, 看着好像是str被改變了,但實際上這是一種假象,JVM對上述代碼是這樣處理的。 1.執行第一行代碼:新建一個String對象「abcdef」(該對象保存在字符串常量池中)將「abcdef」對象的實例引用賦值給str(保存在棧中)。 2.執行第二行代碼: 再新建一個String對象str,用來執行str + "123456"操做,也就是說,str這個對象是沒有發生改變的(String不可變)。每當用String操做字符串時,其實是在不斷的建立新的對象,而原來的對象就會變爲垃圾被GC回收掉,可想而知這樣執行效率會有多低。 一個特殊例子:app
String str = "This is a" + "special" + "example"; StringBuilder stringBuilder = new StringBuilder("This is a").append("special").append("example");
你會發現生成str對象的速度簡直太快了,而這個時候StringBuilder速度上根本一點都不佔優點。 其實這是JVM的一個把戲,實際上:String str = "This is a" + "special" + "example";
其實就是: String str = 「This is a special example」;
因此不須要太多的時間了。 要注意的是,若是你的字符串是來自另外的String對象的話,速度就沒那麼快了,譬如:ui
String str2 = "This is a"; String str3 = "special"; String str4 = "test"; String str = str2 +str3 + str4;
這時候JVM會規規矩矩的按照原來的方式去作。線程
1.若是要操做少許的數據用 --> String 2.單線程操做字符串緩衝區 下操做大量數據 --> StringBuilder 3.多線程操做字符串緩衝區 下操做大量數據 --> StringBuffercode