String的兩種賦值是不同的,String str1=“hello”,指向堆內存中的"hello",而String str2=new String("hello"),因為new開辟的新的堆內存,所以二者地址不同,在用==時,顯示的是false。
例一:
String str1=“Hello”;
String str2=“Hello”;
String str3=“Hello”;

這時候三者都是指向同一堆內存地址,因為如果對象池中已經有了相同的字符串聲明時,就不會再重新開辟空間了。
可是,如果先用String str1=new String("hello"),開辟新的堆內存,內容為"hello",
這時再寫String str2="hello"呢,第一句中new已經新開辟了,對象池中就存在了"hello",
這時第二句中應該指向已經存在的地址,也就是和第一句new開辟的時同一堆內存地址呀,
但是為什么用==時,顯示的還是false呢?
求解答
因為每一個字符串都是一個String類的匿名對象,所以首先會在堆內存中開辟一塊空間保存字符串“Hello”,而后又使用了關鍵字 new 開辟的堆內存,而之前定義的字符串常量的堆內存空間將不會有任何的棧內存指向空間,就成為垃圾,等待被GC回收。所以,使用構造方法開辟的字符串對象實際上會開辟兩塊空間,其中有一塊空間將成為垃圾。另外,使用構造方法實例化的String 類對象內容不會保存在字符串對象池中,既不能夠進行共享數據操作。
觀察入池問題:
public class StringDemo(){
public static void main(String[] args){
String str1 = new String( "Hello" );
String str2 = "Hello";
String str3 = "Hello";
System.out.println( str1 == str2 );
System.out.println( str1 == str3 );
System.out.println( str2 == str3 );
}
}
程序運行結果:
false
false
true
通過上面的程序可以發現,使用構造方法實例化的String 對象不會入池,所以,通過構造方法實例化的String類對象只能自己使用。但在String類中為了方便操作提供了一種稱為手工入池的方法: public String intern();
實例:手工入池
public class StringDemo{
public static void main(String[] args){
String str1 = new String( "Hello" ).intern(); //入池
String str2 = "Hello"; //使用池對象
String str3 = "Hello"; //使用池對象
System.out.println(str1 == str2); //true
System.out.println(str1 == str3); //true
System.out.println(str2 == str3); //true
}
}
程序運行結果:
true
true
true
本程序在使用 String 類構造方法實例化對象后又調用了String 類的 intern() 方法,而這個方法就表示將開辟的字符串對象保存在對象池中,所以日后利用直接賦值方式完成的 String 類對象實例化,就可以直接從對象池中取出數據進行操作,而不再需要重新開辟新的對象了。
常見面試題分析: 請解釋String 類的兩種對象實例化方式的區別。
直接賦值:只開辟一塊堆內存空間,字符串的內容可以自動入池,以供下次使用;
構造方法:開辟兩塊堆內存空間,有一塊將成為垃圾,並且不能自動入池,需要使用intern()手工入池。
常見面試題分析:代碼“String s = new String ("mldn");”創建了幾個String 類的實例化對象?
創建了兩個實例化對象,一個是String類的匿名對象“mldn”,另外一個是使用關鍵字new 實例化的String 類對象。