1. 程式人生 > >JAVA String物件和字串常量的關係解析

JAVA String物件和字串常量的關係解析

轉載自:http://blog.csdn.net/sureyonder/article/details/5569366

1 字串內部列表

  JAVA中所有的物件都存放在堆裡面,包括String物件。字串常量儲存在JAVA的.class檔案的常量池中,在編譯期就確定好了。虛擬機器為每個被裝載的型別維護一個常量池。常量池就是該型別所用常量的一個有序集合,包括直接常量(string、integer和float point常量)和對其他型別、欄位和方法的符號引用。

例如,

String s = new String( "myString" );

其中字串常量是"myString",在編譯時被儲存在常量池的某個位置。在解析階段,虛擬機發現字串常量"myString",它會在一個內部字串常量列表中查詢,如果沒有找到,那麼會在堆裡面建立一個包含字元序列[myString]的String物件s1,然後把這個字元序列和對應的String物件作為名值對( [myString], s1 )儲存到內部字串常量列表中。如下圖所示:


  如果虛擬機器後面又發現了一個相同的字串常量myString,它會在這個內部字串常量列表內找到相同的字元序列,然後返回對應的String物件的引用。維護這個內部列表的關鍵是任何特定的字元序列在這個列表上只出現一次。

例如,String s2 = "myString",執行時s2會從內部字串常量列表內得到s1的返回值,所以s2和s1都指向同一個String物件。但是String物件s在堆裡的一個不同位置,所以和s1不相同。

JAVA中的字串常量可以作為String物件使用,字串常量的字元序列本身是存放在常量池中,在字串內部列表中每個字串常量的字元序列對應一個String物件,實際使用的就是這個物件。

2 字串截留intern

在某些上下文環境下,僅僅保留某個字串的一份copy能夠提高記憶體的使用和效率。String類的intern()方法可以截留字串,如果String物件包含的字元序列不在字串常量內部列表中,那麼就把這個String物件包含的字元序列和String物件的引用作為名值對儲存到內部列表中,最後intern()返回一個指向String物件本身的引用;如果String物件包含的字元序列在字串常量內部列表中,那麼就返回列表的名值對中的對應的字串物件引用,而String物件本身的就會被丟棄。

例如,s.intern()就會返回和s2相同的引用,而以前的s物件就會被垃圾回收。

使用intern()要注意,被放到字串內部列表中的字串物件是不會被垃圾回收的,生命週期和整個程式相同,所以如果使用不當會造成記憶體洩露。