2017-05-07 74 views
-1
String Str1= new String("java"); 
String Str3 = new String("java"); 

System.out.println(Str1==Str3); 

第一行代碼創建對象str1,其中的內容"java" init都在String池中和堆中。現在Str3會做什麼?我知道它在堆中創建Str3關於字符串池中的Str3?第三行做什麼?它是否在String池或堆區檢查相等性?我知道它給出了錯誤,但我的問題是,如果Str1和Str3存儲在字符串池==應給予真正的權利,因爲引用是相同的。如何存儲使用new()創建的字符串作爲Java中的文字的重複字符串?

+1

您正在創建'Str3'作爲** new **對象。由於'=='檢查引用,你會得到'false'。 – Maroun

+0

可能重複[如何比較Java中的字符串?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) –

+0

我知道它會給出錯誤。我的問題是如果str1和str2都存儲在字符串池==應給予真實。 – ravi

回答

2

第一行代碼創建對象str1,其中包含字符串池和堆中的內容「java」init。

其實:

  1. 串池堆的一部分。 (這實際上並不涉及你的錯誤觀念,但它有助於讓你的腦海變得直觀)。
  2. 對應於「java」文字的字符串對象由類加載器創建,而不是由該語句創建。它是在加載類時創建的 ...不是代碼運行時。

所以,其實這句話只有在堆中創建一個字符串對象。

現在Str3會做什麼?

第二個語句在堆中創建單個字符串對象...。

根據上面的說明,此語句中使用的「java」字面值的字符串對象是以前創建的。 (事實上​​,如果你查看字節碼文件,你會發現文件常量池中只有一個「java」字符串,所以,類加載器甚至不需要創建兩個字符串實例和兩個字符串實例。一個是創建和interned。)

我知道它在堆中創建Str3 Str3在字符串池中怎麼辦?

沒有。所有字符串文字均在字符串池中創建,並自動將其刪除。

第三行做什麼?它是否檢查字符串池或堆區域中的相等性?

沒有。它測試以查看對象引用是否相同;即如果它們是相同的對象。它實際上並不測試它們在哪裏。

(你實際上不能直接測試一個String是否在池中,甚至不能測試一個對象是否在堆中。 ..如果JVM爲您提供了一種在(常規)堆外分配對象的方法。)

我知道它給出了錯誤,但我的問題是,如果Str1和Str3存儲在字符串池==應給予真正的權利,因爲引用是相同的。

它們不在字符串池中。他們是普通的堆對象。

認爲它這樣,事實==回報false證明,他們不是(兩者)在字符串池。因爲如果他們都在字符串池中,他們會必須是相同的String對象。 。


這裏是JLS上說字符串和身份是什麼:

「此外,文字始終是一個字符串是指String類的同一個實例。這是因爲字符串文字 - 或者,更通常,使用方法String.intern「常量表達式(§15.28)」的值的字符串將被「interned」,以共享唯一實例。「

這個實習發生在班級加載時。


1 - 規格說明沒有說明實習生何時發生。看起來,最近的JVM懶散地解決了一個方法對字符串文字的引用;即,第一次由字節碼解釋器調用該方法時,實施會發生。但是,這並沒有改變上述解釋的實質。

+0

它實際上好像是對應於字面值的字符串被創建並且當它第一次被引用時被實施。 (如果在使用文字前多次調用System.identityHashCode(「j」.concat(「ava」).intern())和System#gc,它將打印不同的散列碼,在使用文字後它總是打印相同的哈希碼)。 – Nevay

+0

@Nevay它與'之前'和'之後'無關。如果您在類的文本或任何其他已加載的類中使用了全部*全部*,*全部*的全部*,則它將在執行前存在於字符串池中。 – EJP

+0

@EJP那麼你如何解釋這個結果呢? https://ideone.com/204QnH在我看來,它非常清楚地表明,在第一次使用該文字之前,該類的常量池不包含對字符串池中的字符串的引用。 – Nevay

相關問題