1. 程式人生 > >Java String為什麼是不可變類,StringBuffer與StringBuilder區別

Java String為什麼是不可變類,StringBuffer與StringBuilder區別

熟悉Java的都知道String類是不可變,但String類為什麼設計成不可變類,如何做到不可變沒有仔細想過。

String為什麼設計成不可變類?

1.符合Java字串池的設計方式。    
String s1="abc";
String s2="abc";
      Java通過字串池的設計方式節省記憶體空間,如上一段程式碼只會生成一個物件放在常量池當中。s1和s2都指向這個物件,如果String類可變,通過s1這個引用就可以修改這個物件,那其他引用就會受影響。 2.安全性。       JDK提供的眾多API當中,大多的引數都是String型別,如類載入函式,資料庫的連線,Sql語句,Socket的引數等。如果String類可以被修改就會造成安全漏洞。而且多執行緒情況下,String類資料也可以保護資料不被其他執行緒修改。

String怎麼實現不可變?

public final class String  
    implements java.io.Serializable, Comparable<String>, CharSequence {  
    private final char value[];
從String類的原始碼中可以看到,String是通過char value[]儲存字元的。而且宣告為private final,並且不提供我們寫value的介面。所以String類不能夠修改。 (其實String類並不是不能修改,可以通過java的反射機制,獲取到string物件的class物件,把value屬性private修改為可訪問型別,然後就可以直接訪問物件value屬性了)
StringBuffer和StringBuilder的區別 StringBUffer和StringBuilder都是可變的字串類,StringBuffer和StringBuilder類的區別也在於StringBuffer是執行緒安全的,很多方法都有synchronized關鍵字,如下程式碼。StringBuilder不是執行緒安全的,所以一般情況下StringBuilder的效能要好。
 //StringBuffer類的原始碼   
public synchronized void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > value.length) {
            expandCapacity(minimumCapacity);
        }
    }

    /**
     * @since      1.5
     */
    public synchronized void trimToSize() {
        super.trimToSize();
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    public synchronized void setLength(int newLength) {
        super.setLength(newLength);
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    public synchronized char charAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        return value[index];
    }