-
1 # Java從入門到架構師
-
2 # 郎宏林
堆和棧是Java程式在執行過程中的資料儲存區,棧是stack,堆是heap。
堆主要用來儲存使用new關鍵字建立的Java物件和資料,堆中儲存的物件和資料都有相應的記憶體地址值。當堆中儲存的物件和資料不再被使用時,Java的JVM會啟動垃圾回收機制,自動清除堆中儲存的物件和資料。
棧是用來儲存臨時資料的,如Java物件的引用,函式內部的資料和臨時物件,函式執行完畢後,儲存在棧中的臨時資料會立即被釋放。
-
3 # Java程式設計技術
問題中的String指的應該是java中的String吧。這裡給出的回答針對java。
String是一個不可變的物件,在java中只能作為常量使用。java程式碼中所有的顯式字串,即直接寫出的那種字串,例如"abc"都是String物件。String本身作為一個物件,必然是在堆上的,而String中的內容char[] value 則是放在堆中的一個特殊區域中——常量區。
所以String本身是放在堆上,而根據垃圾回收情況,又可以分為新生代和老年代。如果這個String物件剛建立不久,則它一般位於堆的新生代,如果它建立之後存在了很長時間,則它很可能處於堆中的老年代。注意,String中的字串內容即字元陣列value則位於堆中的常量區。
如果你先有一個字元陣列,例如char[] arr { "a", "b", "c" },然後呼叫String s = new String(arr);建立的String,則字元陣列不再是位於常量區,而是跟其他物件一樣,位於堆上。注意,即使這個arr陣列是在棧上分配的,這樣建立的String中的value依然是在堆上。如果你想把這個字串放進常量區,可以呼叫String.intern。
棧上不會有物件,只會有基本變數和引用變數,所以String只可能位於堆上,不可能位於棧上。
回覆列表
在Java中,字串是特殊的。Java特別注意字串型別,其他型別則沒有這種型別。例如,要建立字串物件,您無需使用“ new ”關鍵字。要建立其他型別的物件,必須使用“ new”關鍵字。像這樣,字串受到Java的特別注意。這種注意值得一陣,因為在開發任何型別的應用程式時,幾乎在所有地方都使用了字串。
眾所周知,JVM將分配給Java程式的記憶體分為兩部分。一個是堆疊,另一個是堆。堆疊用於執行目的,堆用於儲存目的。在該堆記憶體中,JVM分配了一些專門用於字串文字的記憶體。堆記憶體的這一部分稱為字串常量池。
每當您使用字串文字建立字串物件時,該物件都會儲存在字串常量池中,而每當您使用new關鍵字建立字串物件時,此類物件都會儲存在堆記憶體中。
例如,當您建立如下所示的字串物件時,它們將儲存在字串常量池中。
String s1 = "abc";
String s2 = "xyz";
String s3 = "123";
String s4 = "A";
並且當您使用如下所示的new關鍵字建立字串物件時,它們將儲存在堆記憶體中。
String s5 = new String("abc");
char[] c = {"J", "A", "V", "A"};
String s6 = new String(c);
String s7 = new String(new StringBuffer());
這就是字串常量池在記憶體中的外觀。
關於字串常量池的另一件有趣的事情是,根據物件的內容將池空間分配給物件。池中不會有兩個物件具有相同的內容。
當您使用字串文字建立字串物件時,就會發生這種情況,
“當您使用字串文字建立字串物件時,JVM首先檢查要建立的物件的內容。如果池中存在具有相同內容的物件,則它將返回該物件的引用。它不會建立新物件。如果內容與現有物件不同,則只能建立新物件。”
但是,當您使用new關鍵字建立字串物件時,無論內容是否相同,都會建立一個新物件。
這可以透過使用“ ==”運算子來證明。如果兩個物件在記憶體中具有相同的物理地址,則“ ==”運算子將返回true,否則它將返回false。在下面的示例中,s1和s2使用字串文字“ abc”建立。因此,s1 == s2返回true。其中,s3和s4是使用具有相同內容的新運算子建立的。但是,s3 == s4返回false。
public class StringExamples
{
public static void main(String[] args)
{
//Creating string objects using literals
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //Output : true
//Creating string objects using new operator
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3 == s4); //Output : false
}
}
簡單來說,字串常量池中不能有兩個內容相同的字串物件。但是,堆記憶體中可以有兩個內容相同的字串物件。