2013-10-24 66 views
3

我想了解字符串池如何工作。我經歷了很多網站,最後我現在更加困惑。讓我在這裏放下疑慮。有人幫助我理解它們。Java字符串池相關的疑惑

1)字符串池在哪裏存在?在堆中還是在方法區?

2)String s = "Hello world"; - 這就夠了創建string.Since字符串是不可改變的,一旦創建字符串不能被改變,那麼就是用 String s = new String(「Hello World」)創建的字符串的需要?
雖然它強制JVM在堆中而不是String pool中創建一個新的String對象。但是強制JVM用於新的String對象的需要是什麼?

3)字符串何時以及如何被垃圾收集?

在此先感謝。

回答

4

的如何將字符串管理的實際執行不應該是間接在Java中,除了保證:

  1. 串x =「喜」; String y =「hi」; //保證x == y
  2. String x =「hi」; String y = new String(「hi」); ==雖然可能不保證== =
  3. String x = new String(「hi」); String y = new String(「hi」); //保證!=但x.equals(y)
  4. String x =「hi」; String y = new String(「hi」)。intern(); //保證X ==Ÿ

這些都是,String.intern()和字符串常量(String x = "hi")中對分配給字符串規則....

在過去的(這將Java8改變)內存模型中的PermGen空間。

因此,他們有不同的GC機制,並且即使您有大量可用堆空間(PermGen是/通常小於128MB),如果您使用了String.intern(),也有可能導致內存不足。

new String(....)分配的字符串在其他常規堆上,並且具有標準的GC機制。

至於爲什麼你/我們使用new String ("...")來創建字符串的新實例,我只能想到一個地方只有這樣做纔有意義,也就是說,如果有人想使用結果對象作爲同步鎖。這在調試事物時是有意義的.....但沒有多大意義。你必須使用'new',這樣你纔不會像其他代碼一樣使用相同的String對象來進行同步。

在一般的Java編程實踐中,我通常沒有見過使用new String ("....")的人。事實上,人們大多隻使用字符串連接運算符等。但是,這並不意味着它是錯誤的當我看到String的源代碼時,我發現代碼在很大程度上依賴於String是不可變的。所以,例如,新的String(new String(「hi」));只創建一個char數組,並且它在兩個String實例中共享。 (並且內部實例無論如何都將是GC'd)。

0

1。字符串池不是STACK,也不是HEAP!這是方法區! 字符串池屬於常量池。因爲我們都知道,CONSTANT是一個不能改變的價值,給予一個不變的池的目的是加快程序的速度。在您的Class文件中,如int a = 10, String b = "123450"正在被視爲字符串(您可以在方法中更改它們)。加載類時,JVM會將它們放入數組中以進行維護。並把這個數組放在名爲String Pool的METHOD區域中。

2.當你創建一個String對象時,你可以這樣做: String str1 = new String("abc")Stirng str2 = "abc";。它們看起來一樣,但JVM以不同的方式處理它們。首先,JVM將在HEAP中創建一個String對象。並將對象返回給用戶。但是對於第二種情況,JVM將通過使用String的equals()方法來檢查字符串池是否存在String的對象。如果是,則將String的對象返回給用戶,並且不會重新創建String的新對象。如果String池沒有String對象,JVM會在HEAP中創建一個新的對象並返回給用戶,同時JVM將把它放到String池中。

String str1 = new String("abc"); //jvm creates a String object in Heap. 

//jvm can not find "abc" in String pool 
//Create a String object in heap,and put it in strings pool 
//Now heap has two string object. 
Stirng str2 = "abc"; 

if(str1 == str2){ 
     System.out.println("str1 == str2"); 
}else{ 
     System.out.println("str1 != str2"); 
} 
    //Print result is str1 != str2, because they are different objects in heap 

    String str3 = "abc"; 

//Now,jvm realizes String Pool already had 「abc」 object,because 「abc」equals 「abc」 

    if(str2 == str3){ 
     System.out.println("str2 == str3"); 
    }else{ 
     System.out.println("str2 != str3"); 
    } 
//Print result is str2 == str3 



String str1 = new String("abc"); 

str1 = str1.intern(); 


Stirng str2 = "abc"; 

if(str1 == str2){ 
     System.out.println("str1 == str2"); 
}else{ 
     System.out.println("str1 != str2"); 
} //Print: str1 == str2 
0

字符串池就像是一個具有String常量的存儲桶。 例如: -

Object a = new Object(); 
Object b = new Object(); 

它會在堆中創建兩個新對象。

但是,

String s1 = "abc"; 
String s2 = "abc"; 

它將String池只能創建一個對象,因爲它們是常數。