2011-06-15 43 views
7

我正在研究基本的Java程序,並且發現了與你分享的有趣的事情。 foo()給出輸出(s == s1)= false,bar給出(s == s1)= true。在Java中使用不同級聯後,爲什麼在比較字符串時會得到不同的結果?

我想知道爲什麼會發生這種情況。

public class StringTest 
{ 
    public static void main(String[] args){ 
    foo(); 
    bar(); 
    } 
    public static void foo(){ 
    String s = "str4"; 
    String s1 = "str" + s.length(); 
    System.out.println("(s==s1) = " + (s1==s)); 
    } 
    public static void bar(){ 
    String s = "str4"; 
    String s1 = "str" + "4"; 
    System.out.println("(s==s1) = " + (s1==s)); 
} 
} 
+1

如果你想比較字符串值,你應該做['equals'](http:// downlo ad.oracle.com/javase/6/docs/api/java/lang/String.html#equals(java.lang.Object)) – asgs 2011-06-15 13:21:47

+0

注意:HTML標記在這裏不起作用來格式化代碼。 – Jesper 2011-06-15 13:22:27

+0

我不知道這個問題是怎麼發生的......;) – Nix 2011-06-15 13:29:14

回答

16

在後一種情況下,編譯器會優化字符串連接。因爲這可以在編譯時完成,所以都引用相同的常量字符串對象。

在前一種情況下,編譯時不能優化length()調用。在運行時,會創建一個新的字符串對象,它與字符串常量不相同(但等於它)

+0

+1解釋*爲什麼*這是它的方式 – Sorrow 2011-06-15 13:23:53

+0

Thanx哥們.. !! – Chakravyooh 2011-06-15 13:27:30

+0

但是如果我在ompersion之後將bar()中的s1的值更改爲..怎麼辦? – Chakravyooh 2011-06-15 13:38:35

3

bar()的串連環可以在編譯時進行,因爲它是什麼組成的表達,但編譯時間常數。雖然在編譯時明顯知道字符串的長度,但編譯器不知道length()返回的是已知值,因此它不會被用作常量。

+0

+1,但是沒有人提到使用'.equals()'來比較字符串是否相等? – Mikaveli 2011-06-15 13:27:48

+1

@Mikaveli:我相信@Chakravyooh知道這一點,但這與問題無關。如果你使用'equals()',那麼這裏有趣的行爲就是隱藏的,那裏的樂趣在哪裏? – 2011-06-15 13:30:06

0

它可能與foo()可能在s中創建新的String實例有關。 length()(。toString()),其中as bar()只是連接一個常量。我不知道它的細節問題,但我的直覺告訴我,它在這個方向

2

當你寫這樣的一行代碼:

String s1 = "str" + "4"; 

那麼編譯器是足夠聰明的優化這個到:

String s1 = "str4"; 

Java中的文字字符串在字符串池中進行管理。如果有兩個文字字符串具有相同的內容(如第二個示例中的ss1),則只會創建一個String對象,這兩個對象將由這兩個變量共享。

Java中的==運算符檢查兩個變量是否引用同一個對象。由於第二個示例中只有一個String對象,因此s == s1將爲true

0

如果我需要猜測,我會說java編譯器對bar()進行了一些優化。在編譯時,很顯然「str」+「4」可以被替換爲「str4」(因爲字符串是不可變的對象)的確是與用於s初始化的「str4」-String相同的對象。

在foo()中,優化不是那種向前推進的。一般而言,s1變量的值不能很容易地預測(事實上,這個例子相當有前途)。所以java編譯器會爲s和s1產生兩個不同的變量。

「==」運算符不會比較字符串的值!它檢查這些是否是相同的對象。要比較字符串的值,請使用「equals」方法,如下所示:

String s = "str4"; 
String s1 = "str" + s.length(); 
System.out.println("(s==s1) = " + (s1.equals(s2)); 
0

您應該嘗試使用String類的intern方法來玩。 Java保留了所有不同字符串存儲在其中的字典。當您創建可在編譯時評估的字符串對象時,Java會在其字典中進行搜索。如果它找到字符串,它只存儲對此字符串的引用(實際上由intern方法返回)。

你應該注意到: "str4" == ("str" + "str4".length())返回false,但 "str4" == ("str" + "str4".length()).intern()返回true,因爲只有「包裝」是一個不同的對象。

2
  • String s1 = "str" + s.length();
  • String s1 = "str" + "4";

在第一種情況下s.length()將返回類型INT的值,在第二情況下的類型是字符串 即使數量是4在這兩種情況下,但類型不一樣:)

相關問題