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