1. 程式人生 > >Java中比較兩個字串是否相等的問題

Java中比較兩個字串是否相等的問題

Java中,關於比較兩個字串是否相等的問題,經常會出現。下面將分析使用 ==(注意:Java中 = 是賦值運算子,== 是比較是否相等) 和 equals()方法 來比較兩個字串相等的區別:

  簡單一句話,==比較的是兩個字串的地址是否為相等(同一個地址),equals()方法比較的是兩個字串物件的內容是否相同(當然,若兩個字串引用同一個地址,使用equals()比較也返回true)。

  字串比較之所以看起來複雜,是因為值型別和引用型別兩種資料型別的區別:值型別,例如 int 型別,當定義並初始化兩個 int 型別的變數,int i = 1;int j = i,這兩個變數 i , j 存放的的就是1這個值,使用 if(i == j)判斷時,自然返回 i 和 j 是相等的 。引用型別,例如字串型別, 當定義並初始化兩個字串型別的變數,String s = "abc"; String s2 = s; 實際上是隻建立了一個String型別的物件,該物件的值為abc,而 s 和 s2 都引用這一個物件。(關於值型別和引用型別的內容稍後會更新)

 基礎篇:

  下面將舉出兩個例子,分析兩種情況下的字串比較問題:

  例1. 使用new關鍵字宣告兩個String型別的變數

 1          String s1 = new String("abc");
 2        String s2 = new String("abc");
 3 
 4       //分別使用.equals()和==進行比較
 5         if(s1.equals(s2))
 6       {
 7          System.out.println("可以使用 equals  來比較");
 8       }else
 9       {
10          System.out.println("不可以使用 equals  來比較");
11
     } 12      if(s1 == s2) 13      { 14        System.out.println("可以使用== 來比較"); 15      }else   16     { 17        System.out.println("不可以使用== 來比較"); 18     }

  執行程式發現,用equals比較返回true,用 == 比較返回false。原因如下:

  因為 == 比較的是兩個字串物件的地址是否相同(是否為同一個地址),當使用new關鍵字建立一個物件的時候,該物件單獨佔據一塊儲存空間,存放llg這個字串的值。所以s1 s2兩個字串雖然值相同,但是儲存的地址不是一個地址,例如兩個人都叫l“李四”但是他們的住址不在一個地方。當使用==來比較的時候,比較的是兩個字串的地址是否是同一個,所以返回false。但是使用equals()方法比較這兩個字串,將會比較兩個字串的值是否相同,所以返回true。

  例2. 正常情況下的字串宣告並定義。   

      //宣告並初始化兩個賦值一樣的字串

      String s1 = "abc";
      String s2 = "abc";

      //使用.equals()方法比較兩個字串是否相等
      if(s1.equals(s2))
      {
         System.out.println("可以使用 equals  來比較");
      }else
      {
         System.out.println("不可以使用 equals  來比較");
      }

      //使用 == 比較兩個字串是否相等
        if(s1 == s2)
        {
         System.out.println("可以使用 == 來比較");
        }else
        {
          System.out.println("不可以使用 == 來比較");
        }

  程式經過執行,發現兩個方式都返回true。那麼這是為什麼呢?原因如下:

  一般我們認為,棧中存放基本型別的變數和物件的引用變數,而new出來的物件和陣列存放在堆中。然而除此之外還有一塊區域叫做常量池。像我們通常想String s1 = "abc"; 這樣申明的字串物件,其值就是儲存在常量池中。當我們建立String s1 = "abc"這樣一個物件之後,"abc"就儲存到了常量池中,當我們建立引用String s2 = "abc" 的時候,Java底層會優先在常量池中查詢是否存在"abc",如果存在則讓s2指向這個值,不會重新建立。所以使用 == 比較時,因為地址相同,所以比較的結果是true。

  那麼問題回來了,既然是有常量池,是不是字串如果不是new出來的(一般也不會這麼new,宣告字串變數一般像例2這麼寫),那麼這些字串都是從常量池引用同一個物件,所以用 == 比較就行了?答案是可以。

為什麼要有一個equals呢?難道只因為有人會故意new一個String出來嗎?當然不是,初學者請先理解上面的內容。

進階版:

近期更新