2014-02-25 79 views
-2

其實我正在測試Scanner的功能。
使用java.util.Scanner時字符串的奇怪行爲

我有一個非常簡單的程序,它有一個字符串變量,其中包含「abc」。然後使用next()方法(甚至我嘗試nextLine())從掃描儀讀取其他字符串(值「abc」)。


然後我比較使用==,根據==檢查它們是否相等(我知道我可以與equals方法進行比較,它的工作方式除外),奇怪的是當我比較使用==,即使它們的hashcode()s相等,並且equals()方法返回true ..

import java.util.Scanner; 

public class Tester1234 { 

    public static void main(String[] args) { 

     Scanner scanner=new Scanner(System.in); 
     String str1="abc"; 
     System.out.println("Eneter abc"); 
      String str2=scanner.next(); 

     System.out.println("str1.hascode()"+str1.hashCode()+"\tstr2.hascode()"+str2.hashCode()+"\tstr2.equals(str1)"+str1.equals(str2)); 
     if(str1==str2) 
     { 
      System.out.println("equal"); 
     } 
     else 
     { 
      System.out.println("not equal"); 
     } 

    } 
} 

我想知道它爲什麼表現如此?

謝謝......!

+1

@ mc10我知道這......我想知道爲什麼不與== ......我知道具有相同內容的字符串將指向StringPool中的同一對象...所以如果我這樣做==爲什麼它回來了嗎? – Naren

+0

Opps對不起,事情是,當你做新的字符串時,它會將原始值複製到內部的'最終字符值[]',並根據'value []'生成hashcode,這就是爲什麼你得到相同的equals和hashcode,但'=='失敗,因爲它包裝在駐留在堆中的新對象下。 –

回答

1

你是錯了,因爲對於

我知道內容相同的字符串將指向StringPool同一個對象的聲明...

whitch是硬編碼字符串,是作爲文字真在代碼中。編譯器在編譯時創建字符串池並使用現有引用。但如果你在運行時使用StringBuilder/StringBuffer構建字符串(我相信Scanner在內部),你不是在字符串池中使用實體,這就是爲什麼你會爲同一個字符串內容獲得兩個不同的對象(引用)。解決此類行爲的方法是使用intern(),但是它會影響性能,因爲interned字符串會轉化爲permgen,並且不會被垃圾收集。

1

如果我們創建一個像這樣的字符串...在字符串池中創建

String str1 = "abc"; 

對象str1,如果我們創造

String str2 = new String("abc"); 

那麼,它在堆上創建,意味着另一個新目的。

這就是您的條件if(str1==str2)返回false的原因,因爲這兩者都是不同的對象。

但是哈希碼是相等的,因爲兩者都是​​,所以equals方法返回true

+0

哥們,即使我做\t String str2 = scanner.next();同樣的事情..返回假 – Naren

1

你是對的,哈希碼和等於返回true,因此它將返回true爲str2.equals(str1)。 但str2是新的字符串,因此它有不同的內存地址,這就是爲什麼它不適用於str2==str1。在這裏你比較內存地址而不是字符串的內容。