幾個概念:
堆(heap):對象存放在堆中;當子程序結束運行時,對應的堆空間不會釋放。
棧(stack):基本類型和對象的應用存放在棧中;當子程序結束運行時,對應的棧空間會釋放。
方法區:與java堆一樣,是各個線程共享的內存區域,被描述為java堆的一個邏輯部分。
運行時常量池:是方法區的一部分。當常量池無法再申請到內存時會拋出OutOfMemoryError異常。
String常量池就是一個運行時常量池。常量池中的對象是可以共享的。
String a = "abc";
該語句創建對象的過程:先在常量池中查找是否有內容為"abc"的字符串對象,若有,直接將該對象的引用賦給a;若沒有,則在常量池中創建"abc"對象,再將其引用賦給a。
String a1 = new String("abc");
String a2 = new String("abc");
在常量池沒有"abc"對象的前提下,這兩條語句產生了3個對象,兩個處於堆中的string對象,一個處於字符串常量池string對象。
String a1 = "abc";
String a2 = "abc";
在常量池沒有"abc"對象的前提下,這兩條語句產生了一個對象,位於字符串常量池中。當String a1 = "abc"執行完畢后,JVM會在字符串常量池中創建一個"abc"對象;然后執行String a2 = "abc"時會先在常量池中查詢是否有"abc",如果有,將"abc"的引用賦給a2;如果沒有,在在字符串常量池中創建一個"abc"對象,再賦給a2。
String a1 = new String("abc");
String a2 = new String("abc");
String a3 = "abc";
String a4 = "abc";
在常量池沒有"abc"對象的前提下,這四條語句一共創建了三個對象。String a1 = new String("abc")分別在堆和常量池中創建了"abc"對象,然后String a2 = new String("abc")也在堆中創建了"abc"對象,String a3 = "abc"和String a4 = "abc"都是從常量池中獲取"abc"的引用。
String b1 = "abc";
String b2 = "ab";
String b3 = "ab" + "c";
String b4 = b2 + "c";
其中b1 = b3 ? true;b1 = b4 ? false。String b3 = "ab" + "c"會直接在常量池中查找"abc"對象,若存在,直接引用該對象。
而String b4 = b2 + "c"會生成新的對象,其內部實現是先new一個StringBuilder,然后 append(b2),append("c");然后讓b4引用toString()返回的對象。
String s = "aa" + "bb"這種形式是先將兩個字符串拼接起來,再在常量池中查找拼接過后的字符串對象("aabb");
String s1 = "aa";String s2 = s1 + "bb";這種形式是生成新的對象,這個對象內部實現是先new一個StringBuilder,
然后 append(s1),append("bb");然后讓s2引用toString()返回的對象。
String里面有一個方法:
public String intern()
返回字符串對象的規范化表示形式。 一個初始為空的字符串池,它由類 String 私有地維護。
當調用 intern 方法時,如果池已經包含一個等於此 String 對象的字符串(用 equals(Object) 方法確定),則返回池中的字符串。否則,將此 String 對象添加到池中,並返回此 String 對象的引用。
它遵循以下規則:對於任意兩個字符串 s 和 t,當且僅當 s.equals(t) 為 true 時,s.intern() == t.intern() 才為 true。 所有字面值字符串和字符串賦值常量表達式都使用 intern 方法進行操作。返回:
一個字符串,內容與此字符串相同,但一定取自具有唯一字符串的池。
例:
String str1 = "abbb";
String str2 = new String("abbb").intern();
System.out.println(str1==str2); //true
測試代碼
1 public class TestString { 2 public static void main(String[] args) { 3 String s1 = new String("abc"); 4 String s2 = "abc"; 5 System.out.println("s1 = s2 ? " + (s1 == s2)); //false
6
7 String a1 = new String("aaa"); 8 String a2 = new String("aaa"); 9 String a3 = "aaa"; 10 String a4 = "aaa"; 11 System.out.println("a1 = a2 ? " + (a1 == a2)); //false
12 System.out.println("a1 = a3 ? " + (a1 == a3)); //false
13 System.out.println("a3 = a4 ? " + (a3 == a4)); //true
14
15 String b1 = "abcd"; 16 String b2 = "ab"; 17 String b3 = "ab" + "cd"; 18 String b4 = b2 + "cd"; 19 System.out.println("b1 = b3 ? " + (b1 == b3)); //true
20 System.out.println("b1 = b4 ? " + (b1 == b4)); //false
21
22 String str1 = "abbb"; 23 String str2 = new String("abbb").intern(); 24 System.out.println("str1 = str2 ? " + (str1==str2)); //true
25 } 26 }
打印結果
s1 = s2 ? false a1 = a2 ? false a1 = a3 ? false a3 = a4 ? true b1 = b3 ? true b1 = b4 ? false str1 = str2 ? true
參考:http://www.cnblogs.com/devinzhang/archive/2012/01/25/2329463.html
http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html
http://www.cnblogs.com/xiohao/p/4296088.html
