最近在查线上问题的时候,发现日志里面挺多这种PatternSyntaxException错误的。从日志中可以清楚的知道,出问题的地方就是调用了String的replaceAll方法。等等,这个不就是个普通的替换方法嘛?难道是我用的姿势不对?话不多说,赶紧看一波源码,将bug修复

在大多数人的认知里,replace方法是替换符合的单个字符串,而replaceAll是替换所有符合的字符串。瞄了一下源码,真的打脸了。
/** * Replaces each substring of this string that matches the literal target * sequence with the specified literal replacement sequence. The * replacement proceeds from the beginning of the string to the end, for * example, replacing "aa" with "b" in the string "aaa" will result in * "ba" rather than "ab". 翻译:用指定的文字序列替换与目标文字序列中匹配的每个子字符串 */ public String replace(CharSequence target, CharSequence replacement) { return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); } /** * Replaces each substring of this string that matches the given <a * href="../util/regex/Pattern.html#sum">regular expression</a> with the * given replacement. 翻译:将目标文字序列中与给定的正则表达式匹配的每个字符串替换 */ public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement); }
replace和replaceAll是JAVA中常用的替换字符的方法
- public String replace(char oldChar, char newChar) 在字符串中用newChar字符替代oldChar字符,返回一个新的字符串
- public String replaceAll(String regex,String replacement)使用给定的 replacement 字符串替换此字符串匹配给定的正则表达式的每个子字符串。
区别:
- replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);
- replaceAll的参数是regex,即基于正则表达式的替换,比如,可以通过replaceAll(“\\d“, “*”)把一个字符串所有的数字字符都换成星号;
相同点:
都是全部替换,底层都是调用了Matcher.replaceAll()方法,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串,如果只想替换第一次出现的,可以使用replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串;
另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作;
还有一点注意::执行了替换操作后,源字符串的内容是没有发生改变的。
由于replacAll()方法,被替换的参数支持正则表达式,而我传入的值存在特殊字符,没有进行转义,导致解析失败。
业务需求是将指定的字符串直接全部替换掉,所以只需将replaceAll()方法更换为replace()方法即可,解决问题。
看一个例子
String word1 = "test.test.test"; String word2 = "test.test.test"; String word3 = "test.test.test"; String word11 = word1.replace(".","@"); //test@test@test String word22 = word2.replaceAll(".","@"); //@@@@@@@@@@@@@@ String word33 = word3.replaceFirst(".","@");//@est.test.test System.out.println("word11: " + word11 + ";word22:" + word22 + ";word33: " + word33); System.out.println("word1: " + word1 + ";word2:" + word2 + ";word3: " + word3); word11: test@test@test;word22:@@@@@@@@@@@@@@;word33: @est.test.test word1: test.test.test;word2:test.test.test;word3: test.test.test
由于”.”属于正则表达式的符号(匹配除换行符 \n 之外的任何单字符),所以replaceAll()执行正则替换;此外,我们可以注意到,replaceFirst()这个方法,其实这个方法跟replaceAll()实现是一样的,执行正则替换,只是该方法只替换符合条件的第一个字符或者字符串
- replace()方法是将目标字符串中完全匹配的指定的字符或者字符串全部替换
- replaceAll()和replaceFirst()方法,则是基于正则表达式的替换,比如,通过replace(“\d”,”@”)是把一个字符串中的所有数字替换为@
- 从上面的例子中,执行替换操作之后,其实是返回一个新对象,源字符串的内容则是不变的。