String的疑惑-String對象在內存中的位置

“String倒底奇特在哪裏?”關於這個問題本來想放過它的,但聽說java面試經常考它,而且博友又給我提了不少珍貴的意見,所以準備在盡點力
廢話到此,下面正式開始
 
1.請看下面這幅圖片:
         是否覺得奇怪,在1處爲true,2處爲false!對java有所瞭解都知道“s1==s2"比較的並非它們在的值(那時該用:s1.equals(s2)),而是比較他們在內存中的地址!難道s1,s2引用的是內存中的同一個數據,呵呵,正是如此!
        由於String對象在編程中使用的極爲平凡,故而隨着程序的增長,勢必造成String常量佔有了大量的內存,而且往往包含這大量的冗餘。假設String與其他類的特性相同,勢必造成如下局面:
         從中不難看到,內存中充斥這大量的冗餘常量"pig","dog",而實際上我們只需要兩個常量就可以了。爲了解決這個問題,從而使java更高效的使用內存,JVM留出一塊特殊的內存區域——“String常量池”。(對String夠優待吧)
        所以當編譯器遇到String s1 = "pig";時,首先檢查String常量池中是否有存在"pig", 如果沒有,則將pig放入常量池中,如下圖:
      繼續,當編譯器遇到String s2 = "pig";時,首先檢查String常量池中是否有存在"pig", 如果發現相同的常量"pig", 則只是把指向常量池中現有的,而不創建任何新的String對象。如下:
     到此,我們應該可以弄明白爲什麼1處運行的結果是true了吧!
     同時,我們也可以弄明白我上一篇文章的疑惑了,如果常量池中的發生了變化,則s1,s2將會同時變化,這也太可怕了吧,所以java絕對不允許出現這種情況!這也是我們常說的那句話:String對象不可改變!
         PS:由於擔心String常量池出現問題,String類被標識爲final
        下面這個例子可能更加讓你無法質疑,我就不在這裏廢話了:
public class Test {

  public static void main(String[] args) {

    String s1 = "pig";

    Person person = new Person();
    person.name = "pig";

    System.out.println(person.name == s1);// 輸出爲true

  }

}
Person.java
public class Person    {
  public String name;

}
 
    至於2處爲false,這表明在String s3 = new String("pig")這種情況下,因爲我們使用了new 關鍵字,所以將在常規內存(非String常量池)中創建了一個新的String對象,並且將引用它(到此和普通的對象一樣)。此外,常量"pig"將放置在池內。
    衆多面試答案中所說的String s3 = new String("pig");創建了兩個對象,一個引用(句柄)是否指如下狀態:(這裏只是猜測,希望哪位高人給個正確答案,或者驗證方法,小弟在此先行謝過!)
s3==s4比較的是s3,s4引用對象的地址,自然不相同,所以2處運行爲false。
 
參考資料:《SCJP學習指南》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章