1. 程式人生 > >java中的字串到底是在方法區的常量池裡還是new出來的物件裡

java中的字串到底是在方法區的常量池裡還是new出來的物件裡

String實質是字元陣列,兩個特點:1、該類不可被繼承;2、不可變性(immutable)

例如 String s1 = new String("myString");

和 String s1 = "myString"; 

第一種方式通過關鍵字new定義過程:在程式編譯期,編譯程式先去字串常量池檢查,是否存在“myString”,如果不存在,則在常量池中開闢一個記憶體空間存放“myString”;如果存在的話,則不用重新開闢空間,保證常量池中只有一個“myString”常量,節省記憶體空間。然後在記憶體堆中開闢一塊空間存放new出來的String例項,在棧中開闢一塊空間,命名為“s1”,存放的值為堆中String例項的記憶體地址,這個過程就是將引用s1指向new出來的String例項

第二種方式直接定義過程:在程式編譯期,編譯程式先去字串常量池檢查,是否存在“myString”,如果不存在,則在常量池中開闢一個記憶體空間存放“myString”;如果存在的話,則不用重新開闢空間。然後在棧中開闢一塊空間,命名為“s1”,存放的值為常量池中“myString”的記憶體地址

轉載自:https://zhidao.baidu.com/question/1431032825282549579.html

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

就速度來說,有如下關係: 

    暫存器 > 棧 >堆 >其他

這裡我們主要關心棧,堆和常量池,對於棧和常量池中的物件可以共享,對於堆中的物件不可以共享。棧中的資料大小和生命週期是可以確定的,當沒有引用指向資料時,這個資料就會消失。堆中的物件的由垃圾回收器負責回收,因此大小和生命週期不需要確定,具有很大的靈活性。

    對於字串:

其物件的引用都是儲存在棧中的,

如果是編譯期已經建立好(即直接用雙引號定義的)的就儲存在常量池中

如果是執行期(即new出來的)才能確定的就儲存在堆中

對於equals相等的字串,在常量池中永遠只有一份,在堆中有多份。

如以下程式碼:

Java程式碼  

String s1 = "china";  

String s2 = "china";  

String s3 = "china";  

String ss1 = new String("china");  

String ss2 = new String("china");  

String ss3 = new String("china");  

對於通過 new 產生一個字串(假設為 ”china” )時,會先去常量池中查詢是否已經有了 ”china” 物件,如果沒有則在常量池中建立一個此字串物件,然後堆中再建立一個常量池中此 ”china” 物件的拷貝物件。並把ss1指向堆中的地址。(在常量池中建立目的是為了提升字串的訪問效率

再例子:

String s5 = new String("Hello"); //先在常量池中建立,再在堆中建立,返回的數值s5是堆中的地址
String s6 = s5.intern();         //返回的數值s6 ,是常量池中的地址
String s10 = "Hello";            //返回的數值s10,是常量池中的地址

System.out.println(s5 == s6);   //輸出false

System.out.println(s6 == s10);  //輸出true

這也就是有道面試題:

 String s = new String(“xyz”); 產生幾個物件?一個或兩個,如果常量池中原來沒有 ”xyz”, 就是兩個。

對於基礎型別的變數和常量:變數和引用儲存在棧中,常量儲存在常量池中。

轉載自:https://blog.csdn.net/u012031380/article/details/54981472