A. java中字元串池存放在內存的哪個區域
字元串首先是一個對象。
舉個例子:
String
str0
=
"abc";
String
str1
=
new
String("abc");
當執行String
str0
=」abc」;時,JVM會在棧中創建三個char型的值
』a』
,
』b』
和
』c』
,然後在堆中創建一個String對象,它的值(value)是剛才在棧中創建的三個char型值組成的數組{
』a』
,
』b』
,
』c』
},最後這個新創建的String對象的值」abc」會被添加到字元串池中。如果我們接著執行String
str1=new
String(」abc」);代碼,由於」abc」已經被創建並保存於字元串池中,因此JVM只會在堆中新創建一個String對象,但是它的值(value)是共享前一行代碼執行時在字元串池中的
」
abc
」
;
B. Java:字元串在JVM常量池中是如何存儲的呢
首先你要知道jvm常量池也是對象池,它和在堆中的存儲沒有區別(底層存儲都是一樣的,只是對象之間的引用有差別)。那為什麼要有常量池呢?因為它可以節省時間和空間,當需要一個對象的時候,可以直接從常量池中獲取,而不需要重新創建,這樣也就節省了時間和空間(常量池判斷對象是否存在應該是equals方法)。
除了String外,Java的8種基本類型(Byte, Short, Integer, Long, Character, Boolean, Float, Double)除Float和Double以外,其它六種都實現了常量池。
樓主這么好學,我出個題目給樓主:
Integer i = 127;
Integer j = 127;
System.out.println(i == j);
提示:對象存在常量池
Integer m = 128;
Integer n = 128;
System.out.println(m == n);
提示:對象存在堆內存
C. java中字元串常量放在哪裡
str1和str2分別
創建兩個對象 Hello對象和str引用對象
兩個必須存放在堆中
str指向堆中的Hello對象
也就是說 兩個對象和str的地址全部存放在堆中
String str="abc"; * 引用數據類型肯定存放在堆中 棧中放置的是參數變數而不能放對象 對象只能放在堆中
它只創建一個對象 在堆中創建一個對String類的對象引用變數str(引用變數肯定是存放在堆里的),然後查找棧中是否有"abc",若沒有則將"abc"存放進棧,並令str指向"abc",若已經存在則直接令str指向"abc".(也就是說引用變數本身只能存放在堆中 它的值是所指向的字元串abc 它的地址存放在棧中) 它創建多個"abc"字元串在內存中其實只存在一個對象而已,這樣有利於節省內存空間同時在一定程度上提高程序運行速度
String str=new String("abc");* 所以通過new操作符的操作都是在堆完成的
它創建兩個對象 abc對象和str引用對象 兩個必須存放在堆中 str指向堆中的abc對象 也就是說 兩個對象和str的地址全部存放在堆中 因為使用了new操作符 所以下面的例子里str2,str3和str4即使是值都為abc因為str2的地址在棧中 str3和str4的地址各自開辟空間 所以他們的地址肯定不一樣了
但是它們的值是一樣的 那就是abc
String str2 = "abc";
String str3=new String ("abc");
String str4 =new String ("abc");
equals:equals就是比較值 ==在基本類型里也是比較值 在引用類型里是比較地址 注意這個區別就OK了!
表示堆中的引用變數的值是否相同(引用類型變數比較的是他們本身的值,本身的值是通過引用變數地址指向的對象或字元串來得到的,不管這個被指向的字元串或者對象是在棧中還是堆中)
==:表示堆中或者棧中的基本類型的值或者引用變數的地址是否相同(基本類型比較的是他們本身的值,引用類型變數比較的是地址)
當equals為true時,==不一定為true;
D. java中聲明一個字元串變數分別放在內存的哪些地方 比如說String a = "abc"
"abc"是分配在棧中的。
而a只是一個對象,一個指向存放"abc」棧的對象,分配在堆中。
許多人都做過這樣的事情,但是,我們到底聲明了什麼?回答通常是:一個String,內容是「abc」。這樣模糊的回答通常是概念不清的根源。如果要准確的回答,一半的人大概會回答錯誤。
這個語句聲明的是一個指向對象的引用,名為「a」,可以指向類型為String的任何對象,目前指向"abc"這個String類型的對象。這就是真正發生的事情。我們並沒有聲明一個String對象,我們只是聲明了一個只能指向String對象的引用變數。所以,如果在剛才那句語句後面,如果再運行一句:
String string = a;
我們是聲明了另外一個只能指向String對象的引用,名為string,並沒有第二個對象產生,string還是指向原來那個對象,也就是,和s指向同一個對象。
E. java中String類型存儲位置
一、new String都是在堆上創建字元串對象。
當調用 intern() 方法時,
編譯器會將字元串添加到常量池中(stringTable維護),
並返回指向該常量的引用。
二、通過字面量賦值創建字元串(如:String str=」twm」)時,
會先在常量池中查找是否存在相同的字元串,若存在,
則將棧中的引用直接指向該字元串;若不存在,則在常量池中生成一個字元串,
再將棧中的引用指向該字元串。
三、常量字元串的「+」操作,
編譯階段直接會合成為一個字元串。
如string str=」JA」+」VA」,
在編譯階段會直接合並成語句String str=」JAVA」,
於是會去常量池中查找是否存在」JAVA」,從而進行創建或引用。
四、對於final欄位,編譯期直接進行了常量替換(而對於非final欄位則是在運行期進行賦值處理的)。
final String str1=」ja」;
final String str2=」va」;
String str3=str1+str2;
在編譯時,直接替換成了String str3=」ja」+」va」,根據第三條規則,
再次替換成String str3=」JAVA」
五、常量字元串和變數拼接時(如:String str3=baseStr + 「01」;)
會調用stringBuilder.append()在堆上創建新的對象。
六、JDK 1.7後,intern方法還是會先去查詢常量池中是否有已經存在,
如果存在,則返回常量池中的引用,這一點與之前沒有區別,
區別在於,如果在常量池找不到對應的字元串,則不會再將字元串拷貝到常量池,
而只是在常量池中生成一個對原字元串的引用。簡單的說,就是往常量池放的東西變了
原來在常量池中找不到時,復制一個副本放到常量池,1.7後則是將在堆上的地址引用復制到常量池。
舉例說明:
String str2 = new String(「str」)+new String(「01」);
str2.intern();
String str1 = 「str01」;
System.out.println(str2==str1);
在JDK 1.7下,當執行str2.intern();時,
因為常量池中沒有「str01」這個字元串,所以會在常量池中生成一個對堆中的「str01」的引用
(注意這里是引用 ,就是這個區別於JDK 1.6的地方。在JDK1.6下是生成原字元串的拷貝),
而在進行String str1 = 「str01」;字面量賦值的時候,常量池中已經存在一個引用,
所以直接返回了該引用,因此str1和str2都指向堆中的同一個字元串,返回true。
String str2 = new String(「str」)+new String(「01」);
String str1 = 「str01」;
str2.intern();
System.out.println(str2==str1);
將中間兩行調換位置以後,因為在進行字面量賦值(String str1 = 「str01″)的時候,
常量池中不存在,所以str1指向的常量池中的位置,而str2指向的是堆中的對象,
再進行intern方法時,對str1和str2已經沒有影響了,所以返回false。
F. java中的String常量是存放在棧中還是堆中
string 字元串是經過final修飾的,在源碼中就可以看到,所以string str= 「123」聲明的變數str是在棧區存放的,但聲明變數的值『123』是在常量池中存放的,如果是經過 new
String str = new String(123);這樣的,變數名str是在堆區存放的,但『123』還是在常量池中存在,在常量池中存放時會先看常量池中有沒有這個『123』值,有的話就把這個值的地址值賦給堆區中的str,沒有就新建一個;
G. java中,字元串,如何存儲在內存中的哪個區域
字元串在java中是不可變序列,每一個雙引號的字元串序列都是常量,存在常量池中。但String類型的對象,屬於對象范疇,按對象的特性存儲。
H. java字元串常量存放在內存meta space stack native heap pearmgen哪個區域
metaspace:JDK 8的HotSpot JVM現在使用的是本地內存來表示類的元數據,這個區域就叫做元空間。
heap:堆內存用於存放由new創建的對象和數組。
stack:在函數中定義的一些基本類型的變數和對象的引用變數都是在函數的棧內存中分配。
pearmgen:移除永久代(Permanent Generation (PermGen)),從JDK
7開始Oracle就開始行動了,比如:本地化的String從JDK 7開始就被移除了永久代(Permanent Generation )。JDK
8讓它最終退役了。替換者就是元空間。
字元串常量,應該是存放在堆中的。
I. java中字元串池是存在於棧中還是存在於堆中
1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
2. 棧的優勢是,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。另外,棧數據可以共享,詳見第3點。堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態分配內存,存取速度較慢。
3. Java中的數據類型有兩種。
一種是基本類型(primitive types)出於追求速度的原因,就存在於棧中。
出於追求速度的原因,就存在於棧中。
另一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據全部存在於堆中,Java用new()語句來顯示地告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要佔用更多的時間。
4. String是一個特殊的包裝類數據。即可以用String str = new String("abc");的形式來創建,也可以用String str = "abc";的形式來創建。前者是規范的類的創建過程,即在Java中,一切都是對象,而對象是類的實例,全部通過new()的形式來創建。
值得注意的是,一般String類中字元串值都是直接存值的。但像String str = "abc";這種場合下,其字元串值卻是保存了一個指向存在棧中數據的引用!
用new()來新建對象的,都會在堆中創建,而且其字元串是單獨存值的,即使與棧中的數據相同,也不會與棧中的數據共享
使用String str = "abc";的方式,可以在一定程度上提高程序的運行速度,因為JVM會自動根據棧中數據的實際情況來決定是否有必要創建新對象。而對於String str = new String("abc");的代碼,則一概在堆中創建新對象,而不管其字元串值是否相等,是否有必要創建新對象,從而加重了程序的負擔。
J. java中的String常量是存放在棧中還是堆中
系統內存一般情況來說分為四個
heap 堆 放 對象 也就是new 出來的東西
stack 棧 放局部變數
static segment 靜態區 用來放 靜態變數 和字元串常量
data segement 代碼區 用來放代碼的
如果 一個字元串是 String s = "abc";它放在棧里
如果一個字元串 用創建對象的方式 String s = new String("abc");
那它是放在了 堆里 而如果單純的 一個 "abc" 這個輸入字元串常量 是放在static segement里