SOGO論壇
  登入   註冊   找回密碼
查看: 1306|回覆: 3
列印 上一主題 下一主題

[程式設計] Java字串的比較 [複製連結]

Rank: 3Rank: 3

狀態︰ 離線
跳轉到指定樓層
1
發表於 2009-3-28 11:46:54 |只看該作者 |倒序瀏覽
原文刊登在 2002/09/12 Java 週報上

初學Java的人﹐在學習的過程中遇到的第一個不能理解的問題﹐通常就是
字串的比較問題﹐因為他們實在不能理解明明兩個"一樣"的字串﹐為什麼
有時在做相等的比較運算時會得到ture的結果﹐可是有時得到的結果確是
false?這個問題在網路上常常都被提出來討論﹐已經算是一個FAQ到不能
FAQ的問題﹐也許是那些初學者們都沒有買到一本好的教科書﹐書中並沒有
教導他們正確的認識字串﹐要是有認真地讀完筆者寫的書﹐應該就不會被
這個問題所困擾了。好吧!大家都是窮學生買不起五百塊以上的書﹐那筆
者就藉著Java週報的一角﹐詳細地說明字串的比較運算。

嚴格說起來﹐字串在Java中也是一個完整的物件﹐兩個物件要做比較時﹐
首先你得先想清楚你想要比較的東西是什麼。舉個例子來說吧﹐日常生活
中婆婆媽媽們聚在一起總是喜歡比較來比較去的﹐有時後比的是誰家的孩
子功課比較好啦﹐誰的老公賺的錢比較多啦等…。人也是物件的一種﹐當
你把兩個人做比較時﹐你一定是把這兩個人身上的某一個屬性拿出來比較
﹐比如說身高、體重、成績等等﹐所以你要說這兩個人完全相同時﹐一定
是你所拿出來比較的每個屬性的內容都相同。另外一種觀點的比較方式是
﹐一個人有時會有好幾個不同的綽號﹐別的人要經由比較確認之後﹐才知
道原來這幾個綽號指的都是你這個人。

話說回來﹐在Java程式中﹐你要比較兩個物件時﹐首先你要確認要比較的
是兩件物件的內容?還是比較兩個物件變數是否指向同一個物件?如果你
是要比較兩個物件的內容時﹐請使用該物件所提供的"equals"方法。例如:

String str1 = new String("hello");
String str2 = new String("hello");
boolean b1 = str1.equals(str2);
booealn b2 = str2.equals(str1);

上例中用誰的equals方法來使用﹐結果都是一樣的(都是true)﹐不過如果
str1和str2是兩個不同的類別物件﹐意義可就不太一樣了﹐這個問題有空
再說。如果你比較個物件變數指的是不是同一個物件﹐那你就得使用比較
算的"=="運算子。例如:

String str3 = new String("hello");
String str4 = new String("hello");
String str5 = str3;
boolean b3 = str3 == str4;
boolean b4 = str3 == str5;

b3的結果是false﹐b4的結果是true。不知道筆者這樣的解說﹐大家應該
可以清楚的知道什麼時候要使用equals方法﹐又什麼時後要使用"=="運算子。
話再說回來﹐會令初學者感到困惑的是類似下面的例子:

String str6 = "hello";
String str7 = "hello";
boolean b5 = str6.equals(str7);
boolean b6 = str6 == str7;

b5的結果是true﹐b6的結果也是true。為什麼b3的結果會是false﹐而b6
的結果卻是true呢?上面幾個例子中的字串物件﹐不都是"hello"這個字
串嗎?你只說對了一半﹐上面例子中str1到str7所指向的字串物件﹐它
們的"內容"都是"hello"這幾個字母沒錯﹐可是它們指向的可不都是同一
個字串物件!str1到str4這四個物件變數指向的字串物件﹐是經由標準
的物件產生方式(new)所產生出來的﹐就算內容一樣﹐可是還是不同的物
件。就像兩個雙胞胎來說﹐甚至兩個用複製出來的人﹐就算所有的屬性
都一樣﹐兩個人還是不同的個體﹐在地球上佔用不同的空間。==運算子
既然比較的是兩個物件變數是否指向的是同一個物件﹐所以b3的結果會
是false就是這個原因囉。

那b6的結果為什麼會是true呢?這是Java為了效能的考量﹐而使用的一
種技巧。因為字串對於一個應用程式來說﹐使用上是非常的頻繁的﹐如
果每個相同內容的字串物件﹐都佔用不同的記憶空間不是很浪費嗎?而
且JVM也要去處理這些可能只用過一次就不再使用的字串。因此﹐當你用
雙引號來產生一個字串物件時﹐JVM會先到記憶體中一個名叫String Pool
的地方去查詢一下﹐是否裡面已經有這個字串了﹐如果有則直接拿出來
使用;如果沒有就產生一個新的放到裡面去。所以str6和str7指向的字
串物件﹐都是在Stirng Pool中的hello字串物件﹐既然兩個物件變數指
向的是同一個物件﹐那麼用==運算子比較的結果當然就是true了。

被搞的昏頭轉向了嗎?其實就記住筆者最前面所說的﹐當你要比較的是
兩個物件的內容相不相等時﹐請用equals方法﹐如果要比較的是兩個物
件變數指向的是不是同一個物件時、請用==運算子。這樣一來﹐不管是
一般的物件還是字串物件在比較時﹐你就不會感到困惑了。
喜歡嗎?分享這篇文章給親朋好友︰
               感謝作者     

Rank: 5Rank: 5

狀態︰ 離線
2
發表於 2009-4-9 23:28:58 |只看該作者
正好大學剛上到JAVA
我做作業就有這問題
我當時是要某個用new創出來的物件儲存輸入字元(但是沒有nextchar就用字串)
當時輸入"+"
判斷式中  字串=="+"  是false
我當時用偷吃步的方法(找函式把字串第一個字元找出來再來判斷就對了...)
感謝這篇解了我疑惑

Rank: 3Rank: 3

狀態︰ 離線
3
發表於 2009-4-11 20:06:45 |只看該作者
只要分清楚 "字串" 是參考資料型別
就變簡單了
這次JAVA概念基礎 一定要會的

Rank: 2

狀態︰ 離線
4
發表於 2009-7-26 01:09:04 |只看該作者
講得真精闢,
不過在實務上,字串很少被程式員直接new起來使用
而是直接用Literal Values的型式,
  ex: String hello = "Hello World";
因為字串是不可變(immutable)物件(即字串物件一旦生成就不可再改變字串的內容),
所以字串物件總是可以被安全的共用,
故應該避免使用如下的statement:  String hello = new String("Hello World");
產生多個一模一樣的不可變物件而不複使用已存在的物件是
浪費記憶體,耗系統資源(物件在創建時成本比較高)而沒有意義的
所以JVM會有"字串池"以達到字串共享減少系統開銷的機制是很合理的。

或許有人會說字串是可改變的:
String str1 = "hello";
str1 = "world";

乍看之下,str1真的從字串"hello"變成字串"world"
但是說穿了,str1只是一個參考到字串物件的reference,
原本指向字串物件 "hello",後來改指向"另一個"字串物件"world"罷了,
"hello"物件還是"hello"物件,從建創到結束前其值都不會改變(並無法讓"hello"物件的值變成"hello world")

不過原作的範例有助於初學者對字串物件的解理(也是該週報的初衷)。
請注意︰利用多帳號發表自問自答的業配文置入性行銷廣告者,將直接禁訪或刪除帳號及全部文章!
您需要登錄後才可以回覆 登入 | 註冊


本論壇為非營利自由討論平台,所有個人言論不代表本站立場。文章內容如有涉及侵權,請通知管理人員,將立即刪除相關文章資料。侵權申訴或移除要求:abuse@oursogo.com

GMT+8, 2024-11-16 12:16

© 2004-2024 SOGO論壇 OURSOGO.COM
回頂部