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出來嗎?當然不是,初學者請先理解上面的內容。
進階版:
近期更新