Java字串的“朝花夕拾” 字串是我們用得很多的一種類,即便是這樣,字串也有很多讓我們混淆的地方,還有很多我們不是很清楚的地方。常用的用法,大家都已經爛熟,這裡不再重述。只想找出一些平時我們不經意的地方,可能我們已經用過了,但還不是很確定。把它們總結出來,算是“朝花夕拾”吧。 第一、 關於String對象關於String對象的問題,每每在bbs上爭論不休。現在傾向的解釋是:String s = “abc”;這個語句中s是一個引用,它指向對象”abc”。這樣一來,下面的語句:String s1 = “abc”;String s2 = “abc”;就只產生了一個對象,即:”abc”。而String s = new String(“abc”);這個語句中s是一個對象。下面的語句:String s1 = new String(“abc”);String s2 = new String(“abc”);就產生了兩個對象了,它們是s1和s2。有了上面的解釋,我們就不難理解,為什麼我們優先在代碼中使用前一種表達方式,因為前一種方式是引用,不論你在代碼中要使用多少個相同的引用,只產生一個對象。而後一種方式則即使多個對象的內容一樣,它們也是不同的對象,有各自的記憶體開銷;這就大大的增加了我們記憶體的開銷。同樣,下面的代碼以及它們的運行結果也就能解釋了。String s1 = "abc";String s2 = "abc";
String s3 = new String("abc");
代碼:System.out.println(s1==s2);運行結果:true代碼:System.out.println(s1=="abc");運行結果:true代碼:System.out.println(s1.equals(s2));運行結果:trueSystem.out.println(s1==s3);運行結果:false代碼:System.out.println(s3.equals("abc"));運行結果:true 第二、 String與StringBuffer的區別既然語句:String s = “abc”;中的s是一個引用。那麼,在下面的語句:String s = “abc”;s = s+”d”;中,就應該有三個對象:”abc”、”d”和”abcd”。引用s先是指向對象”abc”,後指向對象”abacd”。這樣,我們就能看出String和StringBuffer的區別來。對於下面的代碼:String s = “”;for(int i=0;i<10;i++){
s = s+i;
}我們將產生10多個對象。而下面的代碼:
StringBuffer sb = new StringBuffer();
for(int i=0;i<10;i++){ sb.append(i);}只產生一個對象。所以,在String對象需要進行相加的時候,使用StringBuffer要明顯比使用String優越,特別是在迴圈相加的時候。 第三、 其他基本類型與String的轉化在實際的編碼過程中,經常要將其他的基本類型轉化為String類型,如上面的我們所常用到的例子:String s = “”;for(int i=0;i<10;i++){
s = s+i;
}中,s = s+i;語句中就需要將整型資料i轉化為字串,然後再與s相加。其實,除了s = s+1;的這種轉化方式,還有一種我們大家所不常用到的轉化方式,如下:s = s+Integer.toString(1);經過大家對對上面兩種轉化方法所耗時間的測試,結果發現後面一種轉化方式所耗的時間大大低於前面一種轉化方式所耗的時間。所以大家在編碼的過程中,不妨使用後面的一種轉化方式。 第四、 Object類的toString()的重載toString()方法是Object類的一個公有方法,Object類是Java所有類的父類。因此,任何其他的Java類都能重寫該方法,為己所用。例如,所有的基本類型的封裝類,如:Integer、Float、Double等等,都重寫了toString()方法,功能是將該類型轉化為String類型。對toString()的重寫一般用來提供一些關於這類的基本資料。如對於一個複數類,如下:
public class Complex
{ private double real; private double image; ……}它的toString()方法可以寫為:
public String toString()
{ String ri = “”; if(this.image<0) { ri = ri+”-”+Double.toString(Math.abs(this.image))+”i”;}else{ ri = ri+”+”Double.toString(this.image)+”i”;} return Double.toString(this.real)+ri;}上面的這個toString()方法剛好表達了一個複數的數學運算式,這恰恰是我們在對複數做完運算以後希望得到的結果。又如,對於一個員工類:Employee。我們最常用的、最希望看到的常常是他們的姓名,如下:
public class Employee
{ private String firstName; private String secodeName; …… public String toString() {
return this.firstName+this.secodeName;
}……}所以,在一些類中,重寫toString()方法是很有用的,可能作為顯示資料常常使用,也可能用在調試語句中。 第五、 逃逸字元的問題逃逸字元的問題是我們在編程過程中經常會遇到的問題。如在HTML編程中遇到“>”或“<”的話,瀏覽器會將它們作為HTML的保留字元,如標籤的開始符和結束符來看待,這樣就會出現一些錯誤。又如在JDBC編程中的sql語句中,如果出現了“””或者“’”等引號字元,也會出錯,sql語句會把它們當作一個sql語句的開始或結束符。還有,如URL語句中的“?”等字元,也會造成URL運算式的混亂。等等遇到了上面的這些情況,我們都自己找一些特殊字元對它們加以替換,然後用完後又替換回來,這些特殊的字元就是逃逸字元。但是我們自己去找他們的逃逸字元一是比較麻煩,而是容易出錯,容易出現把逃逸字元張冠李戴的情況。鑒於此,Jakarta Commons包為我們提供了一套關於逃逸字元的解決方案,使用這個方案,我們不需要自己親自去尋找逃逸字元,只需要調用Jakarta Commons包的API即可,如下所示:
String s = "There is always < (less) or > (more) than you want.";
String s1 = StringEscapeUtils.escapeHtml(s);
System.out.println(s1);
String s2 = StringEscapeUtils.unescapeHtml(s1);
System.out.println(s2.equals(s));System.out.println(s2);輸出結果:
There is always < (less) or > (more) than you want.
true
There is always < (less) or > (more) than you want.
是不是很簡單,我們只需要在上面的代碼中引入Jakarta Commons的相應的包即可。 第六、 中英文拆字的問題關於中英文混合句子拆字的問題,是我曾經在bbs上看到的一個同仁的解決方案。覺得很有意思,雖然我到現在也沒有用上,但把它放在這篇文章的總結裡,算是對字串的用法的一個收集吧。我們都知道,Java採用的是Unicode編碼,所有的字元都佔有一個字,兩個位元組。那麼我們在一個中英文混合的句子中,怎麼抽取出來一個個的漢語詞語和英語單詞呢?下面就是一個簡單的解決方案:String s = "我是中ab國人";
byte[] bt = s.getBytes();
int i=0;
while(i<bt.length) { String ss; if(bt[i]<0) { ss = new String(bt,i,2); i += 2; } else { ss = new String(bt,i,1); i++; } System.out.println(ss); } 輸出結果為:我是中ab國人