[改善Java代码]注意方法中传递的参数要求(replaceAll和replace的区别)
有这样一个简单的需求:写一个方法,实现从原始字符串中删除与之匹配的所有子字符串,比如"蓝蓝的天,白云飘"中,删除"白云飘",输出"蓝蓝的天," 代码如下:
public class StringUtils { //删除字符串 public static String remove(String source,String sub){ return source.replaceAll(sub, ""); } }
StringUtils工具类很简单,它采用了String的replace方法,改方法是做字符串替换的,我们来编写一个测试用例,检查remove方法是否正确.
1 import static org.junit.Assert.*; 2 3 import org.junit.Test; 4 5 6 public class StringUtilsTest { 7 @Test 8 public void testRemove() { 9 System.out.println(StringUtils.remove("好是好", "好")); 10 System.out.println(StringUtils.remove("$是$", "$")); 11 assertTrue(StringUtils.remove("好是好", "好").equals("是")); 12 assertTrue(StringUtils.remove("$是$", "$").equals("是")); 13 } 14 }
程序输出:
是
$是$
assertTrue(StringUtils.remove("好是好", "好").equals("是")); 测试的结果是绿条(Green Bar)
assertTrue(StringUtils.remove("$是$", "$").equals("是"));测试的结果是红条
问题出现在replaceAll方法上,改方法确实要传递两个String类型的参数,但是它要求第一个参数是一个正则表达式,符合正则表达式的字符串才会被替换.
对于上面的例子来说,第一个测试案例传递进来的是一个字符串"好",这是一个全匹配查找替换.处理的非常正确.
第二个测试案例传递进来的是"$"符号,"$"符号在正则表达式中表示的是字符串的结束位置,也就说执行完replaceAll后,在字符串结尾的地方加上了空字符串,其结果还是"$是$",所以测试失败....
使用replace方法替代即可,它是replaceAll方法的简化版,可传递两个String参数继续替换.
如果注意查看JDK文档,会发现replace(CharSequence target,CharSequence replacement)方法是在1.5版本之后才开始提供的,在此之前如果要对一个字符串进行全部替换,只能使用replaceAll方法,不过由于replaceAll方法的第一个参数使用了正则表达式,而且参数类型只要是CharSequence就可以(String的父类),所以很容易让使用者误解,稍有不慎就会导致严重的替换错误.
CharSequence的实现关系图:
注意:replaceAll传递的第一个参数是正则表达式