String類型的兩種實例化區別

String類型有兩種實例化的方法:
一種是直接賦值,如String str=“abc”;
另一種是通過new來實例化,如:String str=new String(“abc”);
通過一段測試代碼,我們發現:

  public static void main(String[] args) {
        String str1="abc";
        String str2="abc";
        String str3=new String("abc");
        System.out.println(str1==str2);//true
        System.out.println(str1==str3);//false   
    }

結果運行如圖:
在這裏插入圖片描述
爲什麼會這樣呢?
原因是:String類型直接實例化與new實例化對象是不同的;
在字符串中“==”比較的是字符串的地址;equals比較的是字符串的內容;

如果採用直接賦值 法:
在JVM底層實際上會自動維護一個對象池(字符串對象池),如果現在採用了直接賦值的模式進行String類的對象實例化操作,那麼該實例化對象(字符串內容)將自動保存到這個對象池之中。如果下次繼續引用直接賦值的模式聲明String類對象,此時對象池之中如若有指定內容,將直接進行引用;如若沒有,則開闢新的字符串對象而後將其保存在對象池之中以供下次使用;

如果採用構造方法new實例化一個對象:
該實例化對象卻不會入池,且即使對象池中有該字符串內容,它也會直接開闢新的內存存放該字符串,不會引用池中的任何字符串,與池中的內容完全無關;

所以針對上面的代碼:
String str1=“abc”; 因爲是直接賦值,所以就將該字符串內容直接入池了;
String str2=“abc”;直接賦值,發現字符串對象池中有該字符串內容,所以直接引用了該字符串;導致str1與str2是指向的同一個字符串對象;
String str3=new String(“abc”);new實例化對象,直接開闢新的內存空間,與上面的兩個字符串完全無關,

但是在String類中提供了方法入池操作 public String intern() ;
通過該方法,可以將用new實例化的字符串對象方入對象池中,其工作的過程就會和String直接賦值法工作的過程一樣;

 public static void main(String[] args) {

        String str1="qwe";
        String str2=new String("qwe").intern();
        System.out.println(str1==str2);//true
    }

結果爲:
在這裏插入圖片描述
且兩種實例化對象的方式還有一點不同:
直接賦值法在實例化過程中只會創建一個堆內存空間:
如:String str=“Abc”;
在這裏插入圖片描述

在堆內存上創建一個字符串對象,使棧內存上的對象引用指向該字符串對象;

而通過構造方法實例化字符串對象的方法,在實例化過程中會創建兩個堆內存空間:

如: String str=new String(“Abc”);
在這裏插入圖片描述
在實例化的過程中,首先會創建一個堆內存空間(1)存儲字符串Abc,然後在new時,又創建了一個堆內存空間(2),存放該字符串對象,並使堆內存空間(1)成爲垃圾空間,被回收,接着使棧裏面的引用str指向該字符串對象;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章