String,StringBuffer,StringBuilder的區別及其源碼分析(一)


String,StringBuffer,StringBuilder的區別這個問題幾乎是面試必問的題,這里做了一些總結:

1.先來分析一下這三個類之間的關系(都是通過字符數組來實現的)

  乍一看它們都是用於處理字符串的java類,而且長得也都差不多,相信肯定有人會以為StringBuffer和StringBuilder都是繼承自String這個類,即認為String類是其他兩個類的超類。這種想法似乎很合理,但其實是不對的,事實上StringBuffer和StringBuilder確實是繼承自某個類,但是這個類並不是String,至於是哪個類呢?我i們來看一下JDK源碼:

StringBuffer類部分源碼

StringBuilder類部分源碼


String類部分源碼

  看到這里,這三個類的關系基本清晰:StringBuffer和StringBuilder都繼承自AbstractStringBuilder這個類,而AbstractStringBuilder和String都繼承自Object這個類(Object是所有java類的超類)。所以這三個類之間的關系可以大致表示為:

 

關於AbstractStringBuilder這個類,本人只在JDK1.8中的java.lang包下找到了,而在JDK1.6和JDK1.7中均未找到,似乎是1.8版本新加上去的,各位看官可以試着找找。

2.String是不可變類,而StringBuffer, StringBuilder是可變類

  我們查看這三個類的源碼,發現String類沒有append()、delete()、insert()這三個成員方法,而StringBuffer和StringBuilder都有這些方法,這就很容易理解了(這里就不粘代碼了,大家可以找源碼看看)。所以我們可以歸納如下:

  String —— 字符串常量;

  StringBuffer —— 字符串變量;

  StringBuilder —— 字符串變量。

這里再補充一點:從源代碼仔細追究下去,可以發現StringBuffer和StringBuilder中的append、delete、insert這幾個成員方法都是通過System類的arraycopy方法來實現的,即將原數組復制到目標數組。至於System類的定義和用法,筆者將在之后的文章進行介紹。

3.再來說一下執行速度

  在執行速度上,String < StringBuffer < Stringbuilder 。

  3.1 String < StringBuffer

  這是因為String類是不可變的,即字符串常量,所以每次對 String 類型進行改變的時候其實都等同於生成了一個新的 String 對象,然后將指針指向新的 String 對象。這就會對程序運行產生很大的影響,因為當內存中的無引用對象多了以后,JVM的GC進程就會進行垃圾回收,這個過程會耗費很長一段時間,因此經常改變內容的字符串最好不要用 String類的對象。而如果是使用 StringBuffer 類則結果就不一樣了,每次結果都會對 StringBuffer 對象本身進行操作,而不是生成新的對象,再改變對象引用。所以在一般情況下我們推薦使用 StringBuffer ,特別是字符串對象經常改變的情況下。
  但是在某些特殊情況下, String 對象的字符串拼接其實是被 JVM 解釋成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度並不會比 StringBuffer 對象慢,而特別是以下的字符串對象生成中, String 運行速度是遠要比 StringBuffer 快的:

  但是如果要拼接的字符串來自於不同的String對象的話,那結果就不一樣了:

  這時候使用StringBuffer的運行速度更快,而這是我們編程時的大部分情況。

  3.2 StringBuffer < StringBuilder

  這個結論的原因涉及到線程安全和非線程安全,將在下一節詳細介紹。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM