2015-06-14 52 views
1

爲了理解String對象是如何被創建和存儲的,我嘗試了下面的程序,並且看到了我有查詢的輸出。有人可以幫忙嗎?如何創建並存儲在Java中的字符串?

package corejava.immutable; 

public class StringTester { 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 

     String s1 = "Omkar Patkar"; 
     String s2 = "Omkar Patkar"; 
     String s3 = "Omkar" + " Patkar"; 
     String s4 = "Omkar"; 
     String s5 = s4 +" Patkar"; 
     String s6 = new String("Omkar Patkar"); 

     System.out.println("Hashcode s1 = "+s1.hashCode()); 
     System.out.println("Hashcode s2 = "+s2.hashCode()); 
     System.out.println("Hashcode s3 = "+s3.hashCode()); 
     System.out.println("Hashcode s4 = "+s4.hashCode()); 
     System.out.println("Hashcode s5 = "+s5.hashCode()); 
     System.out.println("Hashcode s6 = "+s6.hashCode()); 

     System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 

     System.out.println("Indentity Hashcode s1 = "+System.identityHashCode(s1)); 
     System.out.println("Indentity Hashcode s2 = "+System.identityHashCode(s2)); 
     System.out.println("Indentity Hashcode s3 = "+System.identityHashCode(s3)); 
     System.out.println("Indentity Hashcode s4 = "+System.identityHashCode(s4)); 
     System.out.println("Indentity Hashcode s5 = "+System.identityHashCode(s5)); 
     System.out.println("Indentity Hashcode s6 = "+System.identityHashCode(s6)); 
     System.out.println("Indentity Hashcode intern s6 = "+System.identityHashCode(s6.intern())); 

     System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 

     System.out.println("s1 == s2 : - "+(s1 == s2)); 
     System.out.println("s1 == s3 : - "+(s1 == s3)); 
     System.out.println("s1 == s4 : - "+(s1 == s4)); 
     System.out.println("s1 == s5 : - "+(s1 == s5)); 
     System.out.println("s1 == s6 : - "+(s1 == s6)); 

     System.out.println("\ns2 == s3 : - "+(s2 == s3)); 
     System.out.println("s2 == s4 : - "+(s2 == s4)); 
     System.out.println("s2 == s5 : - "+(s2 == s5)); 
     System.out.println("s2 == s6 : - "+(s2 == s6)); 

     System.out.println("\ns3 == s4 : - "+(s3 == s4)); 
     System.out.println("s3 == s5 : - "+(s3 == s5)); 
     System.out.println("s3 == s6 : - "+(s3 == s6)); 

     System.out.println("\ns4 == s5 : - "+(s4 == s5)); 
     System.out.println("s4 == s6 : - "+(s4 == s6)); 

     System.out.println("\ns5 == s6 : - "+(s5 == s6)); 

     System.out.println("\ns1 == s6.intern() : - "+(s1 == s6.intern())); 
     System.out.println("s2 == s6.intern() : - "+(s2 == s6.intern())); 
     System.out.println("s3 == s6.intern() : - "+(s3 == s6.intern())); 
     System.out.println("s4 == s6.intern() : - "+(s4 == s6.intern())); 
     System.out.println("s5 == s6.intern() : - "+(s5 == s6.intern())); 


    } 

} 

而且我能看到以下的輸出: - 的S5和S6

Hashcode s1 = 2062602683 
Hashcode s2 = 2062602683 
Hashcode s3 = 2062602683 
Hashcode s4 = 76311326 
Hashcode s5 = 2062602683 
Hashcode s6 = 2062602683 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
Indentity Hashcode s1 = 4337374 
Indentity Hashcode s2 = 4337374 
Indentity Hashcode s3 = 4337374 
Indentity Hashcode s4 = 18019860 
Indentity Hashcode s5 = 31054905 
Indentity Hashcode s6 = 605645 
Indentity Hashcode intern s6 = 4337374 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
s1 == s2 : - true 
s1 == s3 : - true 
s1 == s4 : - false 
s1 == s5 : - false 
s1 == s6 : - false 

s2 == s3 : - true 
s2 == s4 : - false 
s2 == s5 : - false 
s2 == s6 : - false 

s3 == s4 : - false 
s3 == s5 : - false 
s3 == s6 : - false 

s4 == s5 : - false 
s4 == s6 : - false 

s5 == s6 : - false 

s1 == s6.intern() : - true 
s2 == s6.intern() : - true 
s3 == s6.intern() : - true 
s4 == s6.intern() : - false 
s5 == s6.intern() : - false 

身份哈希碼是從S1,S2,S3 ......不同的爲什麼會這樣?

在其中的內存區域中,這些對象創建的? ...對象圖將有助於理解......

+0

所有字符串預計將有一個空格之間......所以他們最後的值被假設是「OMKAR Patkar」 ...... S5和S6將包含類似S1的空間,S2和S3 ......但他們的身份hashcodes與s1,s2和s3不一樣......爲什麼有區別? –

+0

關於字符串有很多問題,它們是如何創建和存儲的,包括字符串池。你是否搜索過並閱讀過它們? – Tom

+1

湯姆...對不起,我看到很多鏈接討論這個話題......我的歉意。下次我會照顧的。 –

回答

1

您已經創建字符串和String對象。字符串文字(如s1和s2)存儲在字符串池中。因爲它們是相同的字符串他們有相同的參考。這是有效的。

字符串對象使用new關鍵字結果在被存儲在堆中的對象創建的。它們的處理方式與其他任何對象相同。使用相同的字符串值創建2個對象將產生2個對象,每個對象都有自己的引用。使用new與字符串池中的字符串文本不具有相同的效率。實習String對象將其移動到String池。

當你比較使用==你是比較它們的引用兩個對象。因此,比較具有相同值的2個字符串文字將導致測試結果爲真。但是,測試用new關鍵字創建的2個對象不會。這就是爲什麼你應該使用equals方法來比較對象。

EDIT從2個字符串文字級聯創建

字符串將導致字符串文字,例如S3。因此,s3具有與s1和s2相同的標識哈希碼。但是,s5是從字符串文字和參考創建的一個字符串文字,導致一個新的對象。這解釋了爲什麼它具有不同的身份哈希碼。

+2

你還沒有解釋爲什麼's5'有一個不同的身份hashcode和's3'沒有。現在,不要把它寫給我,因爲我知道它,而是更新你的答案,所以OP可以閱讀它。 – Tom

+1

@Tom更新建議 - 請讓我知道,如果我誤解了任何東西。 – Romski

+0

謝謝@Romski ...我想,沒有像String pool那樣的專用區域。所有對象都是在堆上創建的。然而,String pool的概念確實有助於實現預期的行爲。我遇到了一個來自javaranch的鏈接,將它作爲對此的回答。 ...非常感謝您的幫助 :) –

0

我搜索更多跨鏈接來自哪個JavaRanch的指甲周圍創建String對象的一般的混亂。我還修改了我的程序以驗證文章中提出的主張。這裏是鏈接: -

http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html

由這是怎麼回事: -

  1. 上堆總是創建的所有對象。字符串對象不是 的例外。
  2. 字符串池或表更像查找,以檢查是否需要爲文字常量(而不是新建)創建對象 ...如果是,則在堆上創建 並注意其在池或表中的引用。
  3. 如果有相同的值的字符串對象已經存在並 參考它在表或字符串池中存在...使用相同的參考 (S1,S2,S3在我們的例子)
  4. 如果使用新創建的String對象,無需查找,只是 去創建一個新的對象,並使用這個新的參考
  5. 如果有人對此對象調用「實習」(按照(4)創建)... 然後在表中查找...並返回字符串匹配字符串 的引用。
  6. 如果使本地變量引用null,則字符串字面值 常量仍將繼續由表或字符串池 引用,因此不會被垃圾回收。

NO特殊區域稱爲字符串池,其中創建的字符串字面常量。這是我從那個鏈接中得到的。如果我錯了,請糾正我。

我通過在程序中添加下列行驗證6.點: -

s1 = s2 = s3 = s5 = s6 = null; 
System.gc(); 
try { 
    Thread.sleep(10000); 
} catch (InterruptedException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 
System.gc(); 
System.out.println("\n\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); 
System.out.println("String literal pool's available or not ?"); 
System.out.println("Omkar Patkar".hashCode()); 
System.out.println(System.identityHashCode("Omkar Patkar")); 

和它們給予同樣的哈希碼和identityhashcode。

Hashcode s1 = 2062602683 
Hashcode s2 = 2062602683 
Hashcode s3 = 2062602683 
Hashcode s4 = 76311326 
Hashcode s5 = 2062602683 
Hashcode s5.intern() = 2062602683 
Hashcode s6 = 2062602683 
Hashcode s6.intern() = 2062602683 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
Indentity Hashcode s1 = 20732290 
Indentity Hashcode s2 = 20732290 
Indentity Hashcode s3 = 20732290 
Indentity Hashcode s4 = 18378667 
Indentity Hashcode s5 = 21722195 
Indentity Hashcode s6 = 12719253 
Indentity Hashcode intern s6 = 20732290 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

String literal pool's available or not ? 
2062602683 
20732290 
相關問題