棧內存
|
堆內存
|
基礎類型,對象引用(堆內存地址)
|
由new創建的對象和數組,
|
存取速度快
|
相對于棧內存較慢
|
數據大小聲明周期必須確定
|
分配的內存由java虛擬機自動垃圾回收器管理。動態分配內存大小
|
共享特性
棧中如果有字符串,則直接引用
如果沒有,開辟新的空間存入值
|
每new一次在堆內存中生成一個新的對象。
|
創建之后值可以改變
|
String類聲明后則不可改變
|
一、棧內存
基礎類型int, short, long, byte, float, double, boolean, char和對象引用
棧的共享特性
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
1、編譯器先處理String str1 = "abc";它會在棧中創建一個變量為str1的引用,然后查找棧中是否有abc這個值,如果沒找到,就將abc存放進來,然后將str1指向abc。
2、 接著處理String str2 = "abc";在創建完b的引用變量后,因為在棧中已經有abc這個值,便將str2直接指向abc。這樣,就出現了str1與str2同時均指向abc的情況。
二、堆內存
new、newarray、anewarray和multianewarray等指令建立
要注意: 我們在使用諸如String str = "abc";的格式定義類時,總是想當然地認為,創建了String類的對象str。擔心陷阱!對象可能并沒有被創建!而可能只是指向一個先前已經創建的 對象。只有通過new()方法才能保證每次都創建一個新的對象。 由于String類的immutable性質,當String變量需要經常變換其值時,應該考慮使用StringBuffer類,以提高程序效率。
三、 == 內存地址比對
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true str1和str2同時指向 棧內存 中同一個內存空間
String str3 = "abc";
String str4 = new String("abc") ;
System.out.println(str3 == str4); //flase str3值在棧內存中,str4值在堆內存中
String hello = "hello" ;
String hel = "hel" ;
String lo = "lo" ;
System.out.println(hello == "hel" + "lo") ; //true
//兩個常量相加,先檢測棧內存中是否有hello如有有,指向已有的棧中的hello空間
System.out.println(hello == "hel" + lo) ; //flase
System.out.println(hello == hel + lo) ; //flase
//lo是在常量池中,不檢查棧內存,在堆中產生一個新的hello
四、 equals 值進行比對
public boolean equals(Object anObject)
將此字符串與指定的對象比較。當且僅當該參數不為 null,并且是與此對象表示相同字符序列的 String 對象時,結果才為 true。
String str5 = "abc";
String str6 = new String("abc") ;
System.out.println(str5.equals(str6)); //true str5的值str6的值比對
五、 intern 棧中值的內存地址
Public String intern()
當調用 intern 方法時
1、如果池已經包含一個等于此 String 對象的字符串(用equals(Object) 方法確定),則返回池中的字符串。
2、將此 String 對象添加到池中,并返回此 String 對象的引用。
String s7 = new String("abc") ;
String s8 = "abc" ;
System.out.println(s7 == s7.intern()) ;//flase;
System.out.println(s8 == s7.intern() );//true
1.檢查棧內存中有沒有abc對象如果有
2.將s7指向pool中abc