天天看點

java源碼解讀之String,StringBuilder,StringBuffer

由于最近正好畢業了,正在找工作~~~參加了幾場面試,發現好多公司都會問String,StringBuilder,StringBuffer三者之間的差別~~說實話,以前沒了解過,是以不知道,其實網上很多都有相關的介紹,但是不了解為什麼!是以今天就打算從源代碼看看三者之間的差別~~~

首先看一下String的源碼:

java源碼解讀之String,StringBuilder,StringBuffer

我們可以看出,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的源碼:

java源碼解讀之String,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關鍵字修飾,是線程安全的。

java源碼解讀之String,StringBuilder,StringBuffer

我們接下來看一下StringBuilder的源碼:

java源碼解讀之String,StringBuilder,StringBuffer

是不是很熟悉阿?對!StringBuilder和StringBuffer在實作上基本一緻,唯一一點差別就是StringBuilder是線程不安全的!!

這就是為什麼兩者的效率為什麼基本一樣的原因~~~~

OK,這樣想必大家就對三者之間的關系有所了解了把~~~