首頁  >  文章  >  Java  >  Java中String、StringBuffer和StringBuilder的區別和堆疊記憶體分配的圖文介紹

Java中String、StringBuffer和StringBuilder的區別和堆疊記憶體分配的圖文介紹

黄舟
黄舟原創
2017-03-04 09:33:061825瀏覽

Java中的String類別是一個很常用,但最不注意其細節的類,因此大多數面試會那這個類做文章。例如String str = new String("hello");開啟了幾個記憶體空間,String和StringBuffer的差別等等。下面就做一個我的理解:

String是一個被final修飾的類,它是不能被繼承的。 StringBuffer也是被final修飾的類別。

一、JVM記憶體劃分

     在java中主要存在4塊內存,這些記憶體空間分別為:堆疊記憶體空間、堆疊記憶體空間、全域資料區、全域碼區

    1、堆疊記憶體空間:保存所有的物件名稱(保所了所引用的堆疊記憶體空間的位址)

    2、堆疊記憶體空間:儲存每個物件的特定內容

    3、全域資料區:儲存static類型的資料屬性(全域資料)

   4、全域程式碼區:儲存所有的方法定義






   在JVM中,堆疊記憶體是記憶體空間存放的是物件實例化的內容(程式的資料),堆疊記憶體存放的是物件的名稱,其內容是指向對應堆的位址。

也可以這麼說:所有的物件名稱都保存在堆疊記憶體中,而物件特定的內容則保持在堆疊記憶體中,引用類型資料必須使用new關鍵字來在堆疊記憶體中開闢空間。 #########二 、Sring的記憶體分配#########   String有一個特殊之處:建構String物件時可以使用new建構也可以使用"hello"直接建構。中兩種方法建議使用第二種。 ######    1、String a = "hello";  #########    2、 String a= new String("hello");######  說明如下:##### #####    1:在堆疊記憶體中定義了一個a物件引用,指向堆疊記憶體的值「hello」記憶體位址。最終開啟了一個記憶體空間###

    2:在堆疊記憶體重定義了一個a物件引用,先指向堆疊記憶體值為「hello」記憶體位址,然後再指向new之後堆疊記憶體為「hello」的位址。最後開啟了兩個空間,第一個空間沒有物件引用,會被JVM垃圾回收。

   圖示如下:

     

 理解上面的程式碼就不難理解以下這些程式碼:

 
package andy.string.test;  
  
/**   
 * @author Zhang,Tianyou   
 * version:2014-11-25 下午4:15:14   
 *  
 *   
 */  
  
public class TestString {  
  
    public static void main(String[] args){  
        String a = "hello";  
        String b = "hello";  
        String c = new String("hello");  
        String d = new String();  
        d = "hello";  
        String e = c;  
          
        System.out.println("a==b ? " + (a== b));  
        System.out.println("a==c ? " + (c== b));  
        System.out.println("a==d ? " + (a== d));  
        System.out.println("a==e ? " + (a== e));  
        System.out.println("c==d ? " + (c== d));  
        System.out.println("c==e ? " + (c== e));  
    }  
}



##其中只有a==b==d 、 c=e。


解釋:

         1、String每new一次堆記憶體不想等,而d在new分配完新位址之後,又放棄new之後的位址,指向a對應的記憶體位址,所以他們是相同的。

         2、「hello」賦值此直接賦值方式所指向的堆疊記憶體空間是一樣的。 String在Java中使用了共享設計,在Java形成一個物件池,這個物件池可以保存多個對象,如果新實例化的物件已經在物件池中存在,就不在重複定義,直接從物件池中取出使用。所  以

               存在的內容時,且將物件指向已執行實例的空間位址。

       3、e直接指向C的記憶體空間。

       4、因此使用String時,建議使用直接賦值方式,以縮小記憶體空間,提升效能。


三、String、StringBuffer和StringBuilder的區別

  1、 String、StringBuffer、StringBuilder都是被final修飾的,是不能夠被繼承改寫的。

  2、 String在實例化之後,其記憶體空間的內容大小是不能夠被修改的;而StringBuffer是一個線程安全的可變字元序列,在實例化之後可以動態的修改堆記憶體中的內容,所以記憶體長度和大小是可變的;StringBuilder實例化之後記憶體大小長度也是可變的,不

   相同之處在於StringBuilder不是執行緒同步,因此操作起來必然比StringBuffer更有效率。

       這是有人會想:

                          str += "andy";

      str的值不是也改變了嗎?

     其實上述程式碼在記憶體中已經開啟了3個空間,分別是:”hello“,”andy“, ”helloandy“,他們的堆內存大小是固定的,最終str指向了”helloandy“的堆地址。如下圖:

           

       而StringBuffer使用時,則只會開啟一塊記憶體空間,可使用append新增delete等作業內容。

      String 每次產生物件都會對系統效能產生影響,特別當記憶體中無引用物件多了以後, JVM 的 GC 就會開始運作,那速度是一定會相當慢的。   而如果是使用   StringBuffer/StringBuilder 類別則結果就不一樣了,每次結果都會對 StringBuffer/StringBuilder 物件本身進行操作,而不是產生 新的對象,然後再改變物件參考。

    
  因而在對一個字串循環賦值時,最好使用StringBuffer(線程安全)或StringBuilder,這樣可以節約內存,提高性能,切記

。               

 以上為Java中String、StringBuffer與StringBuilder的差異與堆疊記憶體分配的圖文所介紹的內容,並有更多相關內容請追蹤PHP中文網(www.php.cn)!


#
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn