讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議53:注意方法中傳遞的參數要求 >

建議53:注意方法中傳遞的參數要求

有這樣一個簡單需求:寫一個方法,實現從原始字符串中刪除與之匹配的所有子字符串,比如在「藍藍的天,白雲飄」中,刪除「白雲飄」,輸出「藍藍的天,」,代碼如下:


public class StringUtils{

//刪除字符串

public static String remove(String source, String sub){

return source.replaceAll(sub,"");

}

}


StringUtils工具類很簡單,它採用了String的replace方法,該方法是做字符串替換的,我們來編寫一個測試用例,檢查remove方法是否正確,如下所示:


assertTrue(StringUtils.remove("好是好","好").equals("是"));


測試的結果是綠條(Green Bar),正確無誤,但是再看看如下的測試用例:


assertTrue(StringUtils.remove("$是$","$").equals("是"));


上面只是把「好是好」中的兩個「好」字替換成了一個「$」符號,猜猜結果會是什麼,應該也是綠條吧?但是非常遺憾,結果是紅條,測試未通過。就這麼簡單一個的替換,為什麼測試通不過呢?

問題就出在了replaceAll方法上,該方法確實需要傳遞兩個String類型的參數,也確實進行了字符串替換,但是它要求第一個參數是一個正則表達式,符合正則表達式的字符串才會被替換。對上面的例子來說,第一個測試案例傳遞進來的是一個字符串「好」,這是一個全匹配查找替換,處理得非常正確,第二個測試案例傳遞進來的是「$」符號,「$」符號在正則表達式中表示的是字符串的結束位置,也就是說執行完repalceAll後,在字符串結尾的地方加上了空字符串,其結果還是「$是$」,所以測試失敗也就在所難免了。問題清楚了,解決方案也就出來了:使用replace方法替代即可,它是repalceAll方法的簡化版,可傳遞兩個String參數繼續替換,與我們的編碼意圖是相吻合的。

讀者如果注意看JDK文檔,會發現replace(CharSequence target, CharSequence replacement)方法是在1.5版本以後才開始提供的,在此之前如果要對一個字符串進行全替換,只能使用replaceAll方法,不過由於replaceAll方法的第二個參數使用了正則表達式,而且參數類型只要是CharSequence就可以(String的父類),所以很容易讓使用者誤解,稍有不慎就會導致嚴重的替換錯誤。

注意 replaceAll傳遞的第一個參數是正則表達式。