2012-11-19 49 views
8

可能重複:
String object creation using new and its comparison with intern method爲什麼相同的java字符串採用相同的地址?

我用繩子玩耍更瞭解他們,我注意到的東西,我無法解釋:

String str1 = "whatever"; 
String str2 = str1; 
String str3 = "whatever"; 
System.out.println(str1==str2); //prints true...that's normal, they point to the same object 
System.out.println(str1==str3); //gives true..how's that possible ? 

如何最後一行是真的嗎?這意味着str1和str3在內存中具有相同的地址。

這是一個編譯器優化,它足夠聰明地檢測到兩個字符串文字是相同的(「無論」),因此將str1和str3分配給同一個對象?或者我在字符串的底層機制中錯過了一些東西?

+1

javac編譯器可以檢測到這種簡單的情況,只爲該字符串分配一次空間並重用它。在運行期間,這是另一回事。 – nhahtdh

+0

http://stackoverflow.com/a/513839/1273830>「因爲這些文字是由編譯器實現的,因此引用同一個對象!」 – Prasanth

回答

5

http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3

正如帖子裏說:

字符串分配,像所有的對象分配,證明在這兩個時間和內存成本。 JVM在實例化字符串文字時執行一些技巧以提高性能並降低內存開銷。爲了減少在JVM中創建的String對象的數量,String類保留了一個字符串池。每次您的代碼創建字符串文字時,JVM都會首先檢查字符串文字池。如果該字符串已存在於池中,則對池實例的引用將返回。如果字符串不存在於池中,則新的String對象實例化,然後放入池中。

7

由於Java有一個唯一的interned實例池,並且String文字存儲在此池中。這意味着第一個「whatever」字符串字面值與第三個「whatever」字面值完全相同的String對象。

作爲文件說:

public String intern()

返回 字符串對象的規範表示。最初爲空的字符串池由String類私有地維護 。

當實習生方法被調用時,如果池已經包含一個 串等於由equals(對象) 方法測定此字符串對象,然後從池中字符串被返回。否則,此 字符串對象將被添加到池中,並返回對此字符串 對象的引用。

因此,對於任意兩個字符串s和t,當且僅當s.equals(t)爲真時,s.intern()== t.intern() 才爲真。

所有文字字符串和字符串值常量表達式都是 interned。字符串文字在Java語言規範

返回的§3.10.5定義:具有相同的內容,因爲這串一串,但 保證是從唯一的字符串池。


+0

要添加一個關於你不應該做的事情string1 == string2,無論如何,因爲它不能保證不會有給定「文本」的兩個實例。始終使用string1.equals(string2)或任何適合您的上下文中的比較。 – philnate

+0

@philnate:正是...... :) – Parth

1

javac編譯器組合了在給定類文件中相同的字符串文字。

但是在運行時,字符串文字使用相同的方法,String.intern()這意味着在不同應用的不同類甚至字符串(其中使用相同對象的相同JVM加起來

2

如果你這樣做:

String str1 = new String("BlaBla"); //In the heap! 
String str2 = new String("BlaBla"); //In the heap! 

那麼你就明確地通過new運營商(和構造函數)創建String對象。 在這種情況下,你必須每個對象指向不同存儲位置。

但是,如果你這樣做:

String str1 = "BlaBla";   
String str2 = "BlaBla"; 

那麼你已經隱含建設。 如果兩個字符串具有相同的值,那麼它們共享相同的存儲空間,這是因爲Java節省了相同字符串的存儲空間! (具有相同值的字符串)

相關問題