Java代碼
String str1="abc";
String str2="abc";
System.out.println(str1==str2);
則這段代碼結果就會是true。執行str1時,會首先檢查字元串池中是否存在"abc",如果有則直接賦給str1,如果沒有則在字元串池中建立一個"abc"然後再賦給str1,當執行到str2時,檢查字元串池已經存在了"abc",是以直接賦給str2,str1與str2指向同一個對象,是以結果為true。
而執行String str=new String("abc")時,不管字元串池中有沒有"abc"都會在堆中建立一個字元串對象然後将其賦給str引用。是以執行如下代碼
Java代碼
String str1=new String("abc");
String str2=new String("abc");
System.out.println(str1==str2);
結果就會為false,因為str1與str2指向的分别是兩個不同的對象。
Java代碼
String str1="abc";
String str2="def";
String str3=str1+str2;
System.out.println(str3=="abcdef");
//結果肯定是為false
因為str3指向堆中的"abcdef"對象,而"abcdef"是字元串池中的對象,因為結果為false。JVM對String str="abc"對象放在常量池中是在編譯時做的,而String str3=str1+str2是在運作時刻才能知道的。new對象也是在運作時才做的。而這段代碼總共建立了5個對象,字元串池中兩個、堆中三個。+運算符會在堆中建立來兩個String對象,也就是說從字元串池中複制這兩個值,然後在堆中建立兩個對象,然後再建立對象str3,然後将"abcdef"的堆位址賦給str3。
而如果
Java代碼
String str="abc"+"def"; //直接将"abcdef"放入字元串池中
System.out.println(str=="abcdef");
//結果為true
String str1="abc";
String str2=str1+"def"; //str1是在堆中建立的對象
System.out.println(str2=="abcdef");
//結果為false
由于字元串對象的大量使用(它是一個對象,一般而言對象總是在堆中配置設定記憶體),Java中為了節省記憶體空間和運作時間(如比較字元串時,==比equals()快),在編譯階段就把所有的字元串文字放到一個字元串池中,而運作時字元串池成為常量池的一部分。字元串池的好處,就是該池中所有相同的字元串常量被合并,隻占用一個空間。
我們知道,對兩個引用變量,使用==判斷它們的值(引用)是否相等,即指向同一個對象:
String s1 = "abc" ;
String s2 = "abc" ;
if( s1 == s2 ) System.out.println("s1,s2 refer to the same object");
else System.out.println("trouble");
這裡的輸出顯示,兩個字元串文字儲存為一個對象。就是說,上面的代碼隻在字元串中建立了一個String對象。
現在看String s = new String("abc");語句,這裡"abc"本身就是pool中的一個對象,而在運作時執行new String()時,将字元串池中的對象複制一份放到堆中,并且把堆中的這個對象的引用交給s持有。ok,這條語句就建立了2個String對象。
String s1 = new String("abc") ;
String s2 = new String("abc") ;
if( s1 == s2 ){ //不會執行的語句}
這時用==判斷就可知,雖然兩個對象的"内容"相同(equals()判斷),但兩個引用變量所持有的引用不同,上面的代碼建立了幾個String 對象? (3個,字元串池中1個,堆中2個。)