由于最近正好畢業了,正在找工作~~~參加了幾場面試,發現好多公司都會問String,StringBuilder,StringBuffer三者之間的差別~~說實話,以前沒了解過,是以不知道,其實網上很多都有相關的介紹,但是不了解為什麼!是以今天就打算從源代碼看看三者之間的差別~~~
首先看一下String的源碼:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1TP3pld41WW4ZVblZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TN2cDOyMTN5ADNxYDM0EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
我們可以看出,String是一個final類型的一個類,不可以被繼承。同時,String底層由char數組實作的~~~
我們先來看一下這個代碼
String s1 =new String("abc")
以上會産生幾個對象呢?
這是面試中經常出現的一個問題~~~
答案是:兩個
為什麼呢?我們來看一下源碼:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
我們可以看你出來,String s1=new String("abc");其實就是将“abc”産生一個對象,并且把該對鄉複制給s1對象~~~
這就是産生兩個對象的原因!!!
同時呢,String産生之後的長度是不可改變的~~~那就有同學問了,s1+=s2是怎麼回事?
其實,那是s1+s2産生一個新的String對象s1,原來的s1對象已經被廢棄掉了~~~~
其實,這樣效率非常的低的~~
而且在多線程的環境下是非同步的,也就是不安全的~~
這就是好多都推薦用StringBuffer或者StringBuilder的原因了~~~
我們看一下StringBuffer的源碼:
StringBuffer繼承于absractStringBuilder
建立方式有四種,其 中StringBuffer sb=new StringBuffer("qqqqq")的建立方式,是将String的長度+16産生一個新的StringBuffer對象,然後在調用apppend()方法将“qqqq”追加到StringBuffer對象中,那我們看一下append()的源碼:
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
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;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}
append()方法内部直接就是調用父類的absractStringBuilder中的append(),在父類的append()中,首先判斷追加後數組的長度是否超出現有長度,超出的話,就将
現有的數組産度擴充為:現有長度*2+2 ,然後在将内容複制到新數組中!!
可見,StringBuffer對象是可變的,長度可變不唯一,遞增規則就是:現有長度*2+2
這樣的話,效率上事要比String要高很多的~~~~
同時,StringBuffer的所用方法都是由synchronized關鍵字修飾,是線程安全的。
我們接下來看一下StringBuilder的源碼:
是不是很熟悉阿?對!StringBuilder和StringBuffer在實作上基本一緻,唯一一點差別就是StringBuilder是線程不安全的!!
這就是為什麼兩者的效率為什麼基本一樣的原因~~~~
OK,這樣想必大家就對三者之間的關系有所了解了把~~~