String在內存中如何存儲(Java)


JDK1.8中JVM把String常量池移入了堆中,同時取消了“永久代”,改用元空間代替(Metaspace)
java中對String對象特殊對待,所以在heap區域分成了兩塊,一塊是字符串常量池(String constant pool),用於存儲java字符串常量對象,另一塊用於存儲普通對象及字符串對象。
string的創建有兩種方法:

public static void main(String[] args) {
    String a = "abc";  //第一種
    String b=new String("abc"); //第二種
    String c = "abc";
    System.out.println(a == b);//false
    System.out.println(a == c);//true
}

對於第一種,此創建方法會在String constant pool中創建對象。jvm會首先在String constant pool 中尋找是否已經存在"abc"常量,如果沒有則創建該常量,並且將此常量的引用返回給String a;如果已有"abc" 常量,則直接返回String constant pool 中“abc” 的引用給String a。
對於第二種,jvm會直接在非String constant pool 中創建字符串對象,然后把該對象引用返回給String b,並且不會把"abc” 加入到String constant pool中。new就是在堆中創建一個新的String對象,不管"abc"在內存中是否存在,都會在堆中開辟新空間。

雖然new String()方法並不會把"abc” 加入到String constant pool中,但是可以手動調用String.intern(),將new 出來的字符串對象加入到String constant pool中。

String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2); //false
System.out.println(s1.intern() == s2); //true

當一個String實例調用intern()方法時,會查找常量池中是否有相同的字符串常量,如果有,則返回其的引用,如果沒有,則在常量池中增加一個等於str的字符串並返回它的引用,由於s2已經在常量池中,所以s1.intern()不會再創建,而是直接引用同一個"aaa"。

例:

    public static void main(String[] args) {
        String s1 = "abc";//字符串常量池
         
        String s2 = "xyz";//字符串常量池
         
        String s3 = "123";//字符串常量池
         
        String s4 = "A";//字符串常量池
        
        String s5 = new String("abc"); //堆里
         
        char[] c = {'J','A','V','A'};
         
        String s6 = new String(c);//堆里
         
        String s7 = new String(new StringBuffer());//堆里
    }

字符串在內存中的存儲情況如下圖所示:

總結:

對於字符串:其對象的引用都是存儲在棧中的,如果是【編譯期已經創建好(直接用雙引號定義的)的就存儲在常量池中】,如果是【運行期(new出來的)才能確定的就存儲在堆中】。對於equals相等的字符串,在常量池中永遠只有一份,在堆中有多份。

 參考:

https://blog.csdn.net/okyoung188/article/details/55506594

https://blog.csdn.net/u010842019/article/details/78830334


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM